我正在制作的程序中有以下代码:
01 public class Clazz<T>
02 {
03 T[] t;
04
05 public Clazz<T> methodA(int... ints)
06 {
07 Clazz<Integer> ints2 = new Clazz<>();
08 int remInd[] = new int[t.length - ints2.t.length];
09 return this;
10 }
11 }
但是当我运行方法methodA
时,我收到此错误:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
at Clazz.methodA(Clazz.java:8)
为什么我会收到此错误?当然,我所展示的代码与所讨论的巨大类相比是不完整的(例如,数组t
在检查其长度时不会为空),但我相信我已经展示了一切重要的东西。为什么不运行?
注意:我正在使用JDK 1.7进行此操作,因此第7行编译并正常工作
无论出于何种原因,我决定实施以下解决方案,并且有效:
01 public class Clazz<T>
02 {
03 T[] t;
04
05 public Clazz<T> methodA(int... ints)
06 {
07 Clazz<Integer> ints2 = new Clazz<>();
08 int remInd[] = new int[t.length - ints2.length()];
09 return this;
10 }
11
12 public int length()
13 {
14 return t.length;
15 }
16 }
虽然这是一个解决方案,但我仍然想知道它的工作原理。
答案 0 :(得分:7)
您缺少初始化T
的代码,但我会假设它看起来像这样。我添加了几行不会改变任何功能但有助于演示错误的行:
public class Clazz<T> {
T[] t = (T[]) new Object[5];
public Clazz<T> methodA(int... ints) {
Clazz<Integer> ints2 = new Clazz<Integer>();
int l1 = t.length;
int l2 = ints2.t.length;
int remInd[] = new int[l1 - l2];
return this;
}
public static void main(String...args) {
Clazz<String> clazz = new Clazz<String>();
clazz.methodA(54, 7);
}
}
使用此代码我可以重现错误。这里的问题在于此代码:
int l2 = ints2.t.length
由于编译器知道ints2
的类型参数,因此知道ints2.t
,因此可以将其视为粗略的等价物:
Integer[] temp = ints2.t;
int l2 = temp.length;
由于Integer[]
是[Ljava.lang.Integer
而不是{{1},因此t
(其类名称为Object[]
)的隐式强制转换失败了一个人不能被投射到另一个人身上。
使用在其他地方记录的泛型类型声明的数组有许多复杂情况。简而言之,我会说,如果你需要一个“通用数组”,而是考虑在各方面声明并将其用作Integer[]
,除了,当你与客户交互时在该类中,您只接受或仅返回Object[]
而不是T
(通过未经检查的演员表返回)。例如,
Object
顺便说一下Object[] t = new Object[5];
public T getSomethingFromArray() {
return (T)t[2];
}
public void setSomethingInArray(T something) {
t[2] = something;
}
的工作原理。看看its code on DocJar。
除了通用数组之外,我认为你不理解隐式转换的想法。这是更短的代码,失败的基本相同的错误:
ArrayList
即使不需要将public class Clazz<T> {
T t = (T) new Object();
public static void main(String...args) {
Clazz<String> clazz = new Clazz<String>();
clazz.t.toString();
}
}
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
at Clazz.main(Clazz.java:6)
...
强制转换为字符串,也只需通过引用 clazz.t
隐式。以下是该编译类的clazz.t
输出:
javap -c
对于原始代码,此处为Compiled from "Clazz.java"
public class Clazz extends java.lang.Object{
java.lang.Object t;
public Clazz();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/Object
8: dup
9: invokespecial #1; //Method java/lang/Object."<init>":()V
12: putfield #3; //Field t:Ljava/lang/Object;
15: return
public static void main(java.lang.String[]);
Code:
0: new #4; //class Clazz
3: dup
4: invokespecial #5; //Method "<init>":()V
7: astore_1
8: aload_1
9: getfield #3; //Field t:Ljava/lang/Object;
//BELOW is the line that will fail
12: checkcast #6; //class java/lang/String
15: invokevirtual #7; //Method java/lang/String.toString:()Ljava/lang/String;
18: pop
19: return
}
的{{1}}输出:
javap -c