Java 中的通用数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1817524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generic arrays in Java
提问by
OK, I've been google'ing the web, and I just can't seem to find any solution to my problem. I found lots of solutions, just not any that fit.
好吧,我一直在用谷歌搜索网络,但似乎找不到任何解决我问题的方法。我找到了很多解决方案,但没有一个适合。
I need to create an array of generics. But the generic type itself extends Comparable. When I try the following:
我需要创建一个泛型数组。但是泛型类型本身扩展了 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;
}
}
The problem is that the Object cannot be cast as a generic that extends Comparable. Is there a way around this?
问题是不能将 Object 转换为扩展 Comparable 的泛型。有没有解决的办法?
采纳答案by cletus
Generics and arrays don't mix, basically. The short answer is that you can work around this problem. The longer answer is that you probably shouldn't and I'll explain why.
泛型和数组基本上不混用。简短的回答是您可以解决这个问题。更长的答案是你可能不应该,我会解释原因。
You could use Array.newInstance()
like this:
你可以这样使用Array.newInstance()
:
private Comparable[] hashtable;
...
hashtable = (Comparable[])Array.newInstance(Comparable.class, tableSize);
but you can'tcreate an array of your parameterized type.
但是您不能创建参数化类型的数组。
Arrays are covariant. That means they retain the type of their elements at runtime. Java's generics are not. They use type erasureto basically mask the implicit casting that is going on. It's important to understand that.
数组是协变的。这意味着它们在运行时保留其元素的类型。Java 的泛型不是。他们使用类型擦除来基本上掩盖正在进行的隐式转换。理解这一点很重要。
So when you create an Object array you can't cast it to, say, a Comparable array (or any other type) because that is not correct.
因此,当您创建 Object 数组时,您不能将其转换为 Comparable 数组(或任何其他类型),因为这是不正确的。
To give you an example. With generics this is perfectly legal:
给你举个例子。对于泛型,这是完全合法的:
List<String> list = new ArrayList<String>();
List<Integer> list2 = (List<Integer>)list;
list.add(3);
It's also why you can't do this:
这也是你不能这样做的原因:
public <T> T newInstance(T t) {
return new T(); // error!
}
ie at runtime there is no knowledge of T's class. This is why the above code is more often written as:
即在运行时不知道 T 的类。这就是为什么上面的代码更常写为:
public <T> T newInstance(T t, Class<T> clazz) {
return clazz.newInstance();
}
because their is no runtime type for the generic argument. But with arrays:
因为它们不是泛型参数的运行时类型。但是对于数组:
String arr[] = new String[10];
Integer arr2[] = (Integer[])arr; // error!
What you should be doing in this case (imho) is not using arrays but using an ArrayList
. In all honesty, there is very little reason to use arrays over an ArrayList
and generics is just one example of that.
在这种情况下你应该做的(恕我直言)不是使用数组而是使用ArrayList
. 老实说,几乎没有理由在 an 上使用数组,ArrayList
而泛型只是一个例子。
For a better and more complete explanation see the (excellent) Java Generics FAQ:
有关更好更完整的解释,请参阅(优秀的)Java 泛型常见问题解答:
Can I create an array whose component type is a concrete parameterized type?
No, because it is not type-safe.
Arrays are covariant, which means that an array of supertype references is a supertype of an array of subtype references. That is,
Object[]
is a supertype ofString[]
and a string array can be accessed through a reference variable of typeObject[]
....
我可以创建一个数组,其组件类型是具体的参数化类型吗?
不,因为它不是类型安全的。
数组是协变的,这意味着超类型引用数组是子类型引用数组的超类型。也就是说,
Object[]
是 的超类型,String[]
并且可以通过类型为 的引用变量访问字符串数组Object[]
。...
回答by Chris Dail
You often run into problems when you need to instantiate something of a generic type. The easiest way to get around this is to pass the class of actually will be stored in on the constructor. This way you can construct from the actual type. Try something like this:
当您需要实例化泛型类型时,您经常会遇到问题。解决这个问题的最简单方法是传递实际将存储在构造函数中的类。这样您就可以从实际类型构造。尝试这样的事情:
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;
}
回答by Dónal
The cast you're attempting
你正在尝试的演员阵容
(T[])(new Object[tableSize]);
fails, because the items in the array are instances of Object. Object does not extend Comparable<String>
, so the cast (T[]) fails because T is defined as:
失败,因为数组中的项是 Object 的实例。对象不扩展Comparable<String>
,因此强制转换 (T[]) 失败,因为 T 定义为:
T extends Comparable<String>
To resolve this problem either:
要解决此问题,请执行以下任一操作:
- Instantiate the array so that it's items are instances of some class that does extend
Comparable<String>
- Change
hashTable
from an Array (which is not a generic type), to a generic collection type, e.g.List<T> hashTable = new ArrayList<T>(tableSize>)
- 实例化数组,以便它的项是某个确实扩展的类的实例
Comparable<String>
- 变化
hashTable
从数组(这不是一个通用型),到一个通用的集合类型,例如List<T> hashTable = new ArrayList<T>(tableSize>)
回答by matt
The other answers here generally all advocate a better approach for this (especially the recommendation to use an ArrayList instead), but a simple answer in this specific case could be to do:
这里的其他答案通常都提倡对此采取更好的方法(特别是建议改用 ArrayList),但在这种特定情况下,一个简单的答案可能是:
hashTable = (T[])(new Comparable[tableSize]);
(i.e. create an array of type raw Comparable instead of Object)
(即创建一个原始 Comparable 类型而不是 Object 类型的数组)
If you properly encapsulate all access to this array inside your Hash object this should work, but (as the other answers explain) you could leave yourself vulnerable.
如果您正确地将对该数组的所有访问封装在您的 Hash 对象中,这应该可以工作,但是(如其他答案所解释的)您可能会让自己容易受到攻击。
回答by vnportnoy
The forced cast suggested by other people did not work for me, throwing an exception of illegal casting.
其他人建议的强制转换对我不起作用,抛出非法转换的异常。
However, this implicit cast worked fine:
但是,这个隐式转换工作正常:
Item<K>[] array = new Item[SIZE];
where Item is a class I defined containing the member:
其中 Item 是我定义的包含成员的类:
private K value;
This way you get an array of type K (if the item only has the value) or any generic type you want defined in the class Item.
通过这种方式,您可以获得 K 类型的数组(如果项目只有值)或您想要在类 Item 中定义的任何泛型类型。