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

Posted

技术标签:

【中文标题】Java 将泛型类型与 Void 进行比较【英文标题】:Java compare generic type with Void 【发布时间】:2015-01-31 20:20:30 【问题描述】:

我在比较 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&lt;T&gt;Class&lt;Void&gt;T.classVoid.class 比较id。 但是 androidStudio 在每个尝试过的情况下都会向我显示错误:(

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

【问题讨论】:

您遇到了什么错误?他们可能会解释为什么每种方法都不起作用...... 我不确定该代码的用途是什么,但 Void 是一个不可实例化的类,因此 intanceof 将始终返回 false 我想使用它来确保 Request 的子类中更详细的泛型类型。我在父子类的其他方法中使用它 【参考方案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) //Incovertible types;无法将 T 转换为 java.lang.Void 我没有收到任何编译错误。你确定你没有搞混什么吗? "if" 将始终返回 false,因为 (null instanceof Anything) 为 false,根据 instanceof 的定义:***.com/questions/2950319/… @kocko -- 但这会让你的答案成为非答案:“你可以这样做”+“这样做总是错误的”==“不要这样做” 【参考方案2】:

你不能那样使用 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()...

【讨论】:

【参考方案3】:

Guice 使用的访问参数类的更好方法是使用这样一个事实:虽然泛型类无法访问其自己的“类”参数,但其子类确实可以访问对于这些论点:见https://***.com/a/18610693/15472

如果你需要这个,要么使用 Guice'TypeLiterals,要么重新实现他们的逻辑。

【讨论】:

【参考方案4】:

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

null 是唯一属于Void 类型成员的值。所以也许你想做的是这个?:

 if (memberOfGenericType == null)
     runAnotherMethod();

关于类型Void

不能创建Void 类型的对象,因为该类只有一个私有构造函数,并且从不从类中调用它。 Void 通常用于这些情况:

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

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

【讨论】:

以上是关于Java 将泛型类型与 Void 进行比较的主要内容,如果未能解决你的问题,请参考以下文章

12Java泛型

将泛型与可能是值或引用类型的 null 进行比较?

JAVA——泛型类和泛型方法(静态方法泛型)

Kotlin 泛型中的 in 和 out

将泛型值推送到 Typescript 中泛型类中的泛型列表

Java之泛型