Java中的泛型数组

Java中的泛型数组,java,arrays,generics,Java,Arrays,Generics,好吧,我一直在用谷歌搜索网络,但我似乎找不到任何解决问题的方法。我找到了很多解决方案,只是没有一个合适 我需要创建一个泛型数组。但是泛型类型本身扩展了可比性。当我尝试以下方法时: public class Hash<T extends Comparable<String>> { private T[] hashTable; private int tableSize; Hash(int records, double load) {

好吧,我一直在用谷歌搜索网络,但我似乎找不到任何解决问题的方法。我找到了很多解决方案,只是没有一个合适

我需要创建一个泛型数组。但是泛型类型本身扩展了可比性。当我尝试以下方法时:

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;
    }
}
公共类哈希{
私有T[]哈希表;
私有int表大小;
散列(整数记录,双加载){
表大小=(int)(记录/加载因子);
tableSize=findNextPrime(tableSize);
hashTable=(T[])(新对象[tableSize]);//错误:Ljava.lang.Object;无法强制转换为[Ljava.lang.Compariable;
}
}

问题是对象不能转换为可比较的泛型。有没有办法解决这个问题?

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

您可以这样使用:

private Comparable[] hashtable;

...

hashtable = (Comparable[])Array.newInstance(Comparable.class, tableSize);
public class Hash<T extends Comparable<String>>
{
  Hash(int records, double load, Class<T> class)
  {
    tableSize = (int)(records / loadFactor);
    tableSize = findNextPrime(tableSize);

    hashTable = java.lang.reflect.Array.newInstance(class, tableSize);
  }

private T[] hashTable;
private int tableSize;

}
但是您不能创建参数化类型的数组


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

因此,当您创建一个对象数组时,您不能将其强制转换为类似的数组(或任何其他类型),因为这是不正确的

举个例子。对于泛型,这是完全合法的:

List<String> list = new ArrayList<String>();
List<Integer> list2 = (List<Integer>)list;
list.add(3);
在这种情况下(imho)应该做的不是使用数组,而是使用
ArrayList
。老实说,没有什么理由在
ArrayList
上使用数组,泛型只是一个例子

有关更好、更完整的解释,请参见(优秀):

我可以创建一个组件类型为具体参数化类型的数组吗? 否,因为它不是类型安全的。

数组是协变的,这意味着 超类型引用数组是一个 子类型数组的超类型 引用。也就是说,
Object[]
是一个
字符串[]
和字符串的超类型 可以通过 类型为
Object[]
的引用变量


当您需要实例化泛型类型的某个对象时,经常会遇到问题。解决此问题的最简单方法是将实际将存储在构造函数中的类传递给构造函数。通过这种方法,您可以从实际类型进行构造。请尝试以下操作:

private Comparable[] hashtable;

...

hashtable = (Comparable[])Array.newInstance(Comparable.class, tableSize);
public class Hash<T extends Comparable<String>>
{
  Hash(int records, double load, Class<T> class)
  {
    tableSize = (int)(records / loadFactor);
    tableSize = findNextPrime(tableSize);

    hashTable = java.lang.reflect.Array.newInstance(class, tableSize);
  }

private T[] hashTable;
private int tableSize;

}
公共类哈希
{
散列(整数记录,双加载,类)
{
表大小=(int)(记录/加载因子);
tableSize=findNextPrime(tableSize);
hashTable=java.lang.reflect.Array.newInstance(类,表大小);
}
私有T[]哈希表;
私有int表大小;
}

您尝试的演员阵容

(T[])(new Object[tableSize]);
失败,因为数组中的项是Object的实例。Object不扩展
Comparable
,所以强制转换(T[])失败,因为T定义为:

T extends Comparable<String>
T
要解决此问题,请执行以下操作之一:

  • 实例化数组,使其项成为某个类的实例,该类扩展了
    Comparable
  • hashTable
    从数组(非泛型类型)更改为泛型集合类型,例如
    List hashTable=new ArrayList(tableSize>)

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

hashTable = (T[])(new Comparable[tableSize]);
(即,创建类型为raw Compariable而非Object的数组)


如果您正确地将对该数组的所有访问封装在哈希对象中,这应该会起作用,但是(正如其他答案所解释的)您可能会使自己处于易受攻击的状态。

其他人建议的强制强制强制转换对我不起作用,引发了非法强制转换的异常

但是,这种隐式转换效果很好:

Item<K>[] array = new Item[SIZE];

通过这种方式,您可以获得类型为K的数组(如果该项只有值)或者您希望在类项中定义的任何泛型类型。

只有难看的解决方案。我是说Java的许多问题之一。您是指不懂语言的人^downvote的可能重复项-请参阅使用Java.lang.reflect.Array.newInstanceThank的答案。非常感谢您!这是一个很好的解释,在其他地方更令人费解web.Thank!
(Comparable[])数组.newInstance(Comparable.class,tableSize)
新建Comparable[tableSize]
具有完全相同的效果。这里有一些错误。
列表=新建ArrayList();列表2=(列表)list;
不编译。
即在运行时不知道T的类
您无法实例化T的实例,因为在编译时您不知道T的类型。“数组是协变的。这意味着它们在运行时保留其元素的类型。Java的泛型不是“不协变的,而是可重新定义的()
Item<K>[] array = new Item[SIZE];
private K value;