Java中的通用数组

44 java arrays generics

好吧,我一直在谷歌上网,我似乎无法找到任何问题的解决方案.我找到了很多解决方案,而不是任何合适的解决方案.

我需要创建一个泛型数组.但泛型类型本身扩展了Comparable.当我尝试以下内容时:

public class Hash<T extends Comparable<String>> {
    private T[] hashTable;
    private int tableSize;

    Hash(int records, double load) {
        tableSize = (int)(records / loadFactor);
        tableSize = findNextPrime(tableSize);
        hashTable = (T[])(new Object[tableSize]);  //Error: Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是Object不能被强制转换为扩展Comparable的泛型.有没有解决的办法?

cle*_*tus 78

基本上,泛型和数组不会混合.简短的回答是你可以解决这个问题.更长的答案是你可能不应该,我会解释原因.

你可以Array.newInstance()像这样使用:

private Comparable[] hashtable;

...

hashtable = (Comparable[])Array.newInstance(Comparable.class, tableSize);
Run Code Online (Sandbox Code Playgroud)

但是您无法创建参数化类型的数组.

数组是协变的.这意味着它们在运行时保留其元素的类型.Java的泛型不是.他们使用类型擦除来基本掩盖正在进行的隐式转换.理解这一点很重要.

因此,当您创建一个Object数组时,您无法将其强制转换为Comparable数组(或任何其他类型),因为这是不正确的.

举个例子.使用泛型,这是完全合法的:

List<String> list = new ArrayList<String>();
List<Integer> list2 = (List<Integer>)list;
list.add(3);
Run Code Online (Sandbox Code Playgroud)

这也是你不能这样做的原因:

public <T> T newInstance(T t) {
  return new T(); // error!
}
Run Code Online (Sandbox Code Playgroud)

即在运行时,不知道T的类.这就是为什么上面的代码更常被写为:

public <T> T newInstance(T t, Class<T> clazz) {
  return clazz.newInstance();
}
Run Code Online (Sandbox Code Playgroud)

因为它们不是泛型参数的运行时类型.但是对于数组:

String arr[] = new String[10];
Integer arr2[] = (Integer[])arr; // error!
Run Code Online (Sandbox Code Playgroud)

在这种情况下你应该做什么(imho)不是使用数组而是使用数组ArrayList.老实说,没有什么理由可以使用数组ArrayList而且泛型就是其中的一个例子.

有关更好和更完整的解释,请参阅(优秀)Java泛型常见问题解答:

我可以创建一个组件类型是具体参数化类型的数组吗?

不,因为它不是类型安全的.

数组是协变的,这意味着超类型引用数组是子类型引用数组的超类型.也就是说,Object[]是一个超类型,String[]并且可以通过类型的引用变量访问字符串数组Object[].

...

  • 这里有一些错误.`List <String> list = new ArrayList <String>(); List <Integer> list2 =(List <Integer>)list;`不编译.`即在运行时不知道T的类`你无法实例化T的实例,因为在_compile_时你不知道T的类型. (4认同)
  • `(Comparable [])Array.newInstance(Comparable.class,tableSize)`与`new Comparable [tableSize]具有*完全相同的效果` (3认同)

mat*_*att 16

这里的其他答案通常都提倡更好的方法(特别是建议使用ArrayList),但在这个特定情况下的一个简单答案可能是:

hashTable = (T[])(new Comparable[tableSize]);
Run Code Online (Sandbox Code Playgroud)

(即创建一个类型为raw Comparable而不是Object的数组)

如果你在Hash对象中正确封装了对这个数组的所有访问权限,这应该有效,但是(正如其他答案所解释的那样)你可能会让自己变得脆弱.