【问题标题】:Java compare generic type with VoidJava 将泛型类型与 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 的子类中更详细的泛型类型。我在父子类的其他方法中使用它

标签: java generics types void


【解决方案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 的定义:stackoverflow.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://stackoverflow.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() {...}
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-22
            • 1970-01-01
            • 1970-01-01
            • 2023-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多