【问题标题】:Generic class with array带数组的泛型类
【发布时间】:2011-06-11 14:30:36
【问题描述】:

我想为我的 Java 项目创建一个自定义泛型类,这就是我的目标 - 我找到了代码作为如何创建泛型数组的示例。

public class RegisterSet<T> {
   private T[] register;
   public <T> RegisterSet(int size) {
      register = (T[])Array.newInstance(T, size);
   }
}

现在,我收到错误 Incompatible types - found: T[], required: T[],这对我来说完全没有意义 - 我该如何解决这个问题?

【问题讨论】:

    标签: java type-conversion generics


    【解决方案1】:

    这很有意义,因为您有两个称为 T 的不同类型参数。但是,修复它相当困难,因为我根本看不出您期望您的代码如何编译。考虑这一点:

    Array.newInstance(T, size);
    

    T 是类型参数的名称...您不能将其用作方法的参数。

    请注意,由于类型擦除,如果您希望能够创建正确类型的数组,则需要指定相关的Class 实例。例如:

    public class RegisterSet<T> {
       private T[] register;
       public RegisterSet(Class<T> clazz, int size) {
          register = (T[])Array.newInstance(clazz, size);
       }
    }
    

    ...但我不确定您在这里尝试使用哪个 Array 类。

    【讨论】:

      【解决方案2】:

      您需要一个包含 T 的 Class 对象的变量。填充它的最简单方法可能是静态工厂方法:

      public class RegisterSet<T> {
         public static <T>RegisterSet<T> create(Class<T> clazz, int size) {
             return new RegisterSet<T>(clazz, size);
         }
      
         private T[] register;
      
         @SuppressWarnings("unchecked")
         private RegisterSet(Class<T> clazz, int size) {
            if (clazz.isPrimitive()) throw new IllegalArgumentException("Cannot create a RegisterSet of primitives"); 
            register = (T[])Array.newInstance(clazz, size);
         }
      }
      

      静态方法让你说

      RegisterSet<String> x = RegisterSet.create(String.class, 42);
      

      略短且重复性更低
      RegisterSet<String> x = new RegisterSet<String>(String.class, 42);
      

      【讨论】:

      • @ApoY2k,因为是静态方法,所以类的类型参数T不在作用域内。 &lt;T&gt; 不是返回类型的一部分,也不是与 RegisterSet&lt;T&gt; 相同的 T 它是一个新的类型变量,可以被赋予不同的名称。它的意思是“这种方法可以用作static RegisterSet&lt;String&gt; create(Class&lt;String&gt; clazz, int size)static RegisterSet&lt;Integer&gt; create(Class&lt;Integer&gt; clazz, int size)等。
      【解决方案3】:

      有两个错误:

      首先:类定义了一个类型 T,其次 Method 定义了它自己的类型 T,但是两个 T 之间没有任何关系。 -- 所以你必须从方法声明中删除额外的 Type T:

      public RegisterSet(int size) {
      

      代替:

       public <T> RegisterSet(int size) {
      

      第二:方法Array.newInstance需要一个Class的实例作为它的第一个参数,但是类型T不是class的实例。 - 您需要在构造函数参数列表中引入一个 Class 类型的新参数,并使用此参数创建数组。

      至少它们应该看起来像:

        import java.lang.reflect.Array;
      
        public class RegisterSet<T> {
          private T[] register;
      
          public RegisterSet(int size, Class<T> clazz) {
             @SuppressWarnings("unchecked")
             T[] register = (T[]) Array.newInstance(clazz, size);
          }
        }
      
        ...
        new RegisterSet<Integer>(5, Integer.class)
      

      【讨论】:

      • 那么新对象的创建会是什么样子?我试过了,例如new RegisterSet(5, Integer) 但这不起作用(显然)-但我没有找到任何关于如何正确操作的示例。
      • 当然不行:因为 Integer 不是类的实例,但是 Integer.class 是,所以你需要写:new RegisterSet&lt;Integer&gt;(5, Integer.class)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      • 2018-05-25
      • 1970-01-01
      • 2011-04-20
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多