2015-10-26 46 views
0

我正在为我的Java期中学习,但在实现类型方面存在一些问题。这里有一个错误的类,但我不明白为什么。有人可以帮助我,也许给我一些解释?当然,错误与实体类型有关。Array and reified type

class Conversion { 
    public static <T> T[] toArray(Collection<T> c) { 
     T[] a = new T[c.size()]; 
     int i = 0; 
     for (T x: c) a[i++] = x; 
     return a; 
    } 
} 
+0

简单的答案是,你不能创建的项目类型从未来的数组一个类型参数。 – biziclop

回答

4

数组是一个具体化类型。这意味着数组的确切类型在运行时是已知的。因此,在运行时,例如,String[]Integer[]之间存在差异。

这不是泛型的情况。泛型是一个编译时构造:它们用于在编译时检查类型,但在运行时确切类型不再可用。在运行时,类型参数只是Object(或者如果类型参数具有上限,则为上限)。所以在运行时,Collection<String>Collection<Integer>的类型没有区别。

现在,当您想创建一个类型参数的数组时,会出现问题。在运行时,不知道什么是T,所以如果你编写new T[10],Java运行时不知道要创建什么类型的数组,String[]Integer[]。这就是为什么你不能以这种方式创建一个数组。

有几个解决方法,其中没有一个是完全令人满意的。通常的解决方法是创建一个Object[],并把它转换到你想要的类型的数组:

T[] theArray = (T[]) new Object[size]; 

但是,你要记住,这是非常不安全的。如果创建的箭头的范围很小,则只应该执行此操作,以便您可以手动确保该阵列仅包含T实例,并且永远不会将其分配给任何无法实现的实例。下面的代码演示了此问题:

public class Foo<T extends Comparable> {  
    T[] createArray() { 
     return (T[])new Object[1]; 
    } 

    public static void main(String... args) { 
     Foo<String> foo = new Foo<>(); 
     String[] ss = foo.createArray(); // here 
    } 
} 

标有此行抛出一个异常,因为你想投的Object[]String[]

如果你真的需要一个正确的运行时类型的数组,你需要使用反射。获取某个类型的令牌,你需要的类型(类型Class<T>的),并使用Array.newInstance(type, cize)创建阵列,例如:

public T[] createArray(Class<T> type, int size) { 
    return (T[]) Array.newInstance(type, size); 
} 
+0

哇!非常感谢你 :) – Francesco

2

您不能创建一个泛型类型的数组。编译器可能会抱怨像“通用数组创建”。有这周围没有很好的方法,但有一个办法做到这一点:

public static <T> T[] toArray(Class<T> type, Collection<T> c) { 
    T[] a = (T[]) Array.newInstance(type, c.size()) 
    … 
} 

你需要Class<T>这一点,但它的工作:)

+0

那么究竟做什么类类型? – Francesco

+1

'类'是类型'T'的类,就像'类'是'String'的类一样。 'Array.newInstance'需要明确的引用它,'T.class'将不起作用,因为'T'本身是不可确定的,所以'toArray'的调用者需要提供它。 – akaIDIOT

+0

非常感谢你 – Francesco

3

Reifiable type由JLS定义:

A型是reifiable当且仅当如下条件之一成立:

  • 它指的是一个非通用类或接口类型声明。
  • 它是一个参数化类型,其中所有类型参数都是无界通配符(§4.5.1)。
  • 它是一种原始类型(§4.8)。
  • 它是一种原始类型(§4.2)。
  • 它是一个数组类型(§10.1),其元素类型是可调整的。
  • 它是一个嵌套类型,其中对于由“。”分隔的每个类型T,T本身是可赋值的。

参见下面§4.7音符,推理很详细的描述。

您的类型参数不属于上述内容,因此无法确定。因而不能在array creation expression使用:

它是一个编译时间错误,如果ClassOrInterfaceType并不表示 一个reifiable类型(§4.7)。否则,ClassOrInterfaceType可能会命名为 任何指定的引用类型,即使是抽象类类型(§8.1.1.1)或 接口类型。

相关问题