提问人: 提问时间:12/21/2008 更新时间:8/9/2013 访问量:9723
Java 中泛型数组的最简单替代方案是什么?
What is the easiest alternative to a generic array in Java?
问:
假设我有这个:
class test<T>
{
private T[] elements;
private int size;
public test(int size)
{
this.size = size;
elements = new T[this.size];
}
}
这似乎是不可能的,因为编译器一旦尝试替换泛型代码或其他东西,就不知道要调用什么构造函数。我想知道的是,我该怎么做?我认为这是可能的,因为它在 C++ 中很容易完成。
编辑:对不起,我忘记了元素声明中的[]。
答:
我可能错了,但你的声明似乎很奇怪,你不应该有:
private T[] elements;
问题在于,由于泛型类型参数是由编译器转换为的(称为类型擦除),因此您实际上创建了一个 .您可以做的是向函数提供:T
Object
Object
Class<T>
class test<T>
{
private T[] elements;
private int size;
public test(Class<T> type, int size)
{
this.size = size;
elements = (T[]) Array. newInstance(type, size);
}
}
你会在这里找到更好的解释: Angelika Langer - 我可以创建一个组件类型为类型参数的数组吗?
泛型数组的最简单替代方法是使用列表。
评论
有两种解决方案不需要传入类对象。在这两种情况下,我都假设,既然它是一个私有变量,你是唯一一个把东西放进去的人,而外界看不到它。
一种是只使用一个普通的Object数组。缺点是你将失去泛型的好处,你将不得不从中转换出来的东西,这使得代码更加丑陋。但是,由于您是唯一将东西放入其中的人,因此演员应该始终是安全的。外面不需要知道发生了什么。Object[]
其他选项是一种黑客攻击。创建一个 ,然后将其“强制”到 。从技术上讲,这是非法的,因为 和 是不同的运行时类型,前者不能强制转换为后者。但是,只要你不将数组传出类(例如返回它或其他东西),那么它就不会引起任何问题,因为无论如何都会被擦除,并且实际上不会执行任何强制转换。然后,您可以在类中获得泛型的好处,以便更轻松地编码,但您必须非常小心,不要将该数组传递给任何实际需要 的人,因为它不是。Object[]
T[]
Object[]
T[]
T[]
Object[]
T[]
出于多种原因,我倾向于避免使用基本数组,并尽可能使用 ArrayLists(或类似的 Lists)。最重要的两个是:
我不需要秃头数组的语义。括号符号(即指针算术的简写)没有什么能让我的生活更轻松。
如果我使用列表,我会根据需要将自己设置为使用更复杂的并发结构。例如,将 ArrayList 替换为 CopyOnWriteArrayList 非常容易。
因此,使用泛型 ArrayList 编写示例将如下所示:
class test<T> {
/** It's not strictly necessary to make this a List vs. an ArrayList
You decide what interface you really need to expose internally. */
private List<T> elements;
/** This parameter isn't necessary with a List. You can always call the
size() method instead. */
private int size;
public test(int size) {
this.size = size;
elements = new ArrayList<T>();
// Note that the next line isn't strictly necessary.
// An ArrayList can be dynamically resized without any real effort on your part.
elements.ensureCapacity(size);
}
}
size 字段看起来确实是多余的。你可以只用 elements.length 而不是 size。
class Test<T> {
private final T[] elements;
public test(int size) {
elements = (T[]) new Object[size];
}
}
或者,可以将 Test 类替换为 ArrayList。即完全放弃类。
评论
另请查看以下代码:
public static <T> T[] toArray(final List<T> obj) {
if (obj == null || obj.isEmpty()) {
return null;
}
final T t = obj.get(0);
final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
for (int i = 0; i < obj.size(); i++) {
res[i] = obj.get(i);
}
return res;
}
它将任何类型的对象列表转换为相同类型的数组。
评论