有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java将泛型类型与Void进行比较

我无法比较java泛型类型是否为Void类型。换句话说,我试图确保我的泛型类型T是否为Void。 我的示例实现:

public abstract class Request<T>{

     private T member;

     protected void comparing(){
         if(T instanceof Void) // this make error "Expression expected"
             runAnotherMethod();

         //if I type
         if(member instanceof Void) //Incovertible types; cannot cast T to java.lang.Void
             runAnotherMethod();
     }

     protected void runAnotherMethod(){...}
}

public class ParticularRequest extends Request<Void>{
}

我试图通过instanceofClass<T>Class<Void>T.classVoid.class来比较id。 但AndroidStudio在每个尝试过的案例中都会显示错误:(

你能帮我比较一下吗? 谢谢


共 (6) 个答案

  1. # 1 楼答案

    可以存储类的泛型类型的private成员

    public abstract class Request<T> {
    
         private T memberOfGenericType;
    
         protected void comparing() {
             if (memberOfGenericType instanceof Sometype)
                 runAnotherMethod();
         }
    
         protected void runAnotherMethod() { ... }
    
         public T getMemberOfGenericType() {
            return memberOfGenericType;
         }
    
         public void setMemberOfGenericType(T value) {
            this.memberOfGenericType = value;
         }
    }
    

    这样,在运行时,memberOfGenericType将具有Sometype类型,并且您将能够编译if语句。您还可以使用我添加的getter在运行时验证memberOfGenericType是否为Sometype

    无论如何,作为旁注,我想说,如果您不将泛型类型用作成员、方法或方法参数的类型,那么就不需要泛型类型,然后您应该重新考虑您的设计。另外,特别是类型Void是不可实例化的,因此您无法为类成员传递有效的实例,这或多或少会使if语句无用

  2. # 2 楼答案

    由于Java中没有作为Void类型实例的对象,因此不能在此处使用instanceof

    null是类型Void的成员的唯一值。那么也许你想做的就是这样

     if (memberOfGenericType == null)
         runAnotherMethod();
    

    关于类型Void

    无法创建类型为Void的对象,因为该类只有一个私有构造函数,并且从未从该类中调用它Void通常用于以下情况:

    • 获取Class对象,该对象表示声明为返回void的方法的返回类型
    • 作为占位符类型参数,当不打算使用该类型的字段和变量时
  3. # 3 楼答案

    你不能像那样使用它。你需要一些例子来比较。例如,某些成员或参数:

    public abstract class Request<T> {
        T member;
    
         protected void comparing(T param){
             if(member instanceof Void)
                 runAnotherMethod();
    
             if(param instanceof Void)
                 runAnotherMethod();
    
         }
    
         protected void runAnotherMethod(){...}
    }
    
  4. # 4 楼答案

    当使用java泛型时,通常需要在构造函数中请求泛型类型的类,以便实际使用该类。我想,这是一个令人困惑的句子,所以请看下面的示例:

    public abstract class Request<T> {
    
        private Class<T> clazz;
    
        // constructor that asks for the class of the generic type
        public Request(Class<T> clazz) {
            this.clazz = clazz;
        }
    
        // helper function involving the class of the generic type.
        // in this case we check if the generic type is of class java.lang.Void
        protected boolean isVoidRequest(){
            return clazz.equals(Void.class);
        }
    
        // functionality that depends on the generic type
        protected void comparing() {
            if (isVoidRequest()) {
                runAnotherMethod();
            }
        }
    
        // ...
    }
    

    当您创建子类时,必须将泛型类型的类传递给超级构造函数

    public class LongRequest extends Request<Long> {
        public LongRequest() {
            super(Long.class);
        }
    }
    
    public class VoidRequest extends Request<Void> {
        public VoidRequest() {
            super(Void.class);
        }
    }
    
  5. # 5 楼答案

    在运行时T被编译为Object,而实际的类是未知的。正如其他人所说,您应该维护参数化类型的实例,但这不是自动的:您需要实例化它,并且构造函数T()不能使用

    而且java.lang.Void不能实例化,所以应该使用另一个类,比如自制的Void

    试着这样做:

    public final class Void {}; // cannot use java.lang.Void, so create another class...
    
    public abstract class Request<T> {
      protected abstract T member(); // A member would need to be initialized...
    
      protected void comparing(T param){
        if(member() instanceof Void) // Use our Void not java.lang.Void
          runAnotherMethod();
    
      }
    
      protected void runAnotherMethod(){...}
    }
    
    public class ParticularRequest extends Request<Void>{
      @Override
      protected Void member() { return new Void(); } // Could be optimized...
    }
    

    编辑:

    我不明白,但是你为什么需要这个。 如果不同类型有不同的子级,那么也可以有不同的实现

    类似于此(类型和方法仅限于示例):

    public abstract class Request<T> {
      protected abstract T method();
    }
    
    public class RequestInt extends Request<Integer> {
      @Override
      protected Integer method() {...}
    }
    
    public class RequestText extends Request<String> {
      @Override
      protected String method() {...}
    }
    
  6. # 6 楼答案

    Guice使用的一种更好的访问参数类的方法是使用这样一个事实:虽然泛型类不能访问自己的“类”参数,但它的子类可以访问这些参数:请参见https://stackoverflow.com/a/18610693/15472

    如果需要,可以使用Guice'TypeLiterals,或者重新嵌入它们的逻辑