我想创建一个包含10个元素堆栈,我试图与泛型做到这一点。 我开始创建类型T的Stack类,但是当我尝试实例化泛型类型的数组时,出现了编译错误。
public class Stack<T>{
private T[] stk = new T[10];
}
我在做什么错在这里?
我想创建一个包含10个元素堆栈,我试图与泛型做到这一点。 我开始创建类型T的Stack类,但是当我尝试实例化泛型类型的数组时,出现了编译错误。
public class Stack<T>{
private T[] stk = new T[10];
}
我在做什么错在这里?
你不能这样做。不是没有使用一些关于代码的hacky round,即使如此,你最终还是必须做一个unsafe
,这完全破坏了首先尝试安全类型的全部理由。
这是因为Java有一些名为type erasure
的东西,编译器会抛弃所有通用信息,而运行时不知道什么是T
。
这里是这样做的首选方式:
@SuppressWarnings("unchecked")
static <T> T[] newArray(Class<T> type, int length)
{
return (T[]) java.lang.reflect.Array.newInstance(type, length);
}
在一个List<T>
实施黑客调用toArray()
天真的解决方案这不创建有关列表实例抛出。
有关此更多的讨论,参见
Here is an answer to a similar question about creating a type safe array at runtime。
你不能创建一个通用型的阵中还有原因是这样的:
当一个泛型类型实例化时,编译器的技术叫做类型擦除转换的类型 - 一个过程,其中编译器中删除所有与类或参数类型有关的信息。 Type erasure使得使用泛型的Java应用程序能够保持与泛型之前创建的Java库和应用程序的二进制兼容性。例如,Box被转换为Box类型,它被称为原始类型 - 原始类型是不带任何类型参数的泛型类或接口名称。这意味着您无法找到泛型类在运行时使用的对象类型。下面的操作是不可能的:
public class MyClass<E> {
public static void myMethod(Object item) {
if (item instanceof E) { //Compiler error
...
}
E item2 = new E(); //Compiler error
E[] iArray = new E[10]; //Compiler error
E obj = (E)new Object(); //Unchecked cast warning
}
}
http://download.oracle.com/javase/tutorial/java/generics/erasure.html
使用泛型的原因是,你不想类型转换。
这就是说,这里有两个解决方案。
public class MyStack2<T> {
Object[] myStack2;
public MyStack2() {
myStack2 = new Object[10];
}
public void push(T t) {
// do whatever you wanna do to push t, like myStack2[x] = t;
}
public T pop() {
// do whatever you wanna do to pop t like return (T)myStack2[0];
// Here we typecasted, but we can be sure that myStack2 contains only T's
// because we garanteed it at the push method.
}
}
OR
您可以:
您可以根据您所提供访问阵列的方法使用对象的数组和garantee你只推和弹出T的使用数组以外的其他东西来存储您的堆栈。
public class MyStack<T> {
Stack<T> myStack;
public MyStack() {
myStack = new Stack<T>();
}
public void push(T t) {
myStack.push(t);
}
public T pop() {
return myStack.pop();
}
}
正如你所看到的,JAVA已经提供了Stack类,这样你就不必写了一个,但如果你真的想这样做,可能了解它是如何工作的,可以更换Stack类在这个例子中由一个List。如果你使用的是数组,你将可以使用与List相同的功能。
不起作用的原因是,当您在Java中编写类似String[]
的类型时,这意味着对象在运行时知道其组件类型为String
(或其子类)。泛型类型参数在运行时不可用,因此您不能这样做。我们希望有类似于Object[]<T>
的东西,即“在运行时不知道其组件类型,但在编译时具有泛型类型检查的数组”,但这种东西在该语言中不存在。
但是,从代码看来,您打算在内部使用此数组,并且您并不在乎数组在运行时是否知道T
;你只需要一个数组,句号。如果你不打算阵列传递出类的,那么有两种选择:
使用Object[]
类型的变量,并创建new Object[10]
。如果你想从方法中返回一个元素,这是一个未经检查的强制转换,这就需要你投到T
。
使用类型T[]
的变量,并使用= (T[])new Object[10]
进行赋值。现在人们会指出,子类型关系在技术上并不真实,但只要它属于课堂内部(在T
范围内),这并不重要,因为T
已被删除。所以使用这种方法时,您必须格外小心,不要传递或返回数组引用,因为您不会被警告它不安全。
这两种方法都是类型擦除后相同,这两种方法都会造成选中投警告,所以它的真的是你的个人喜好。第二种方法更方便(假设它是T[]
,并且没有演员就可以把它弄出来),而第一个更正式,更安全(第二个要求你勤奋不要传递出去)。
由于类型删除无法完成。请参阅http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java。 –
我想你可以,检查这个: 看到这个链接:http://stackoverflow.com/questions/529085/java-how-to-generic-array-creation – sfrj
这似乎是显示了Java问题之一每隔几天。 –