Java如何比较泛型类型和Void?

3

我在比较Java泛型类型时遇到了问题,主要是想确定我的泛型类型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 在每种尝试中都显示错误 :(

你能帮我解决如何进行比较吗? 谢谢。


1
你遇到了什么错误?它们可能会解释为什么每种方法都不起作用... - tucuxi
3
我不确定那段代码的目的是什么,但Void是一个无法实例化的类,因此instanceof永远会返回false。 - Pablo Lozano
我想使用它来确保Request的子类中有更详细的泛型类型。我在父类和子类的其他方法中也使用它。 - feromakovi
6个回答

2
使用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);
    }
}

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 语句几乎无用。

如果我像你的例子那样做,它会在这一行上给我一个错误: if(member instanceof Void) //不可转换的类型;无法将 T 强制转换为 java.lang.Void - feromakovi
我没有收到任何编译错误。你确定你没有搞混什么吗? - Konstantin Yovkov
"if"语句将始终返回false,因为根据instanceof的定义,(null instanceof Anything)为false:https://dev59.com/questions/w3A85IYBdhLWcg3wF_YO - tucuxi
1
@kocko -- 但这样回答就不是一个答案了:“你可以这样做”+“这样做总是错误的” == “不要这样做”。 - tucuxi

0
你不能那样使用T。你需要一些实例进行比较。例如一些成员或参数:
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(){...}
}

0
更好的访问参数类的方法,由Guice使用,是利用一个事实,即虽然通用类不能访问自己的“class”参数,但它的子类可以访问这些参数:请参见https://stackoverflow.com/a/18610693/15472 如果您需要此功能,请使用Guice的TypeLiterals或重新实现它们的逻辑。

0

由于在Java中没有任何属于Void类型的对象实例,因此您无法在此处使用instanceof

null是属于Void类型的唯一值。因此,也许您想要做的是这样的:

 if (memberOfGenericType == null)
     runAnotherMethod();

关于类型Void

由于该类仅具有私有构造函数且从类内部未调用,因此无法创建Void类型的对象。 Void通常在以下情况下使用:

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

0

在运行时,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() {...}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接