ArrayList的get()方法为什么可以直接将Object数组返回成泛型里的类型?
ArrayList的get()方法为什么可以直接将Object数组返回成泛型里的T?今天阅读ArrayList源码时,为什么可以直接在返回类型为泛型的方法里直接返回Object数组,而我自己定义的类里却需要强转?以下是ArrayList源码
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
transient Object[] elementData;
E elementData(int index) {
return this.elementData[index];
}
}
而我的代码却无法编译
回复
1个回答

test
2024-06-18
你这个代码是不是通过 IDE 里的 go to definition 看到的。
对 ArrayList ,这种方式看到的不是实际代码,而是通过反汇编得到的。
而对于这类 generic 函数,类型检查实际上貌似是在最终不再有 generic 类型的调用处发生的,而不是被调函数里。所以反汇编的代码里就看不到类型转换了。
但是实际代码,没有类型转化是无法通过编译的。
这应该是由于类型擦除,在 elementData 函数体是无法得到 E 具体是什么类型的,也就无法进行实际的转换。实际的转换要一直延迟到可以确定 E 的位置才能发生。
package foo;
public class Generic<T> {
public T getObjectFoo() {
return (T) new Object();
}
}
javap -c Generic.class
Compiled from "Generic.java"
public class foo.Generic<T> {
public foo.Generic();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public T getObjectFoo();
Code:
0: new #3 // class java/lang/Object
3: dup
4: invokespecial #8 // Method java/lang/Object."<init>":()V
7: areturn
}
package foo;
public class Foo {
public void A() {
final Generic<Integer> g = new Generic<>();
final Integer i = g.getObjectFoo();
}
}
javap -c Foo.class
Compiled from "Foo.java"
public class foo.Foo {
public foo.Foo();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
public void A();
Code:
0: new #15 // class foo/Generic
3: dup
4: invokespecial #17 // Method foo/Generic."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #18 // Method foo/Generic.getObjectFoo:()Ljava/lang/Object;
12: checkcast #22 // class java/lang/Integer !!!! 实际的类型检查(转换)
15: astore_2
16: return
}
可以看到类型检查(转换)的代码是在 Foo.A 里,而不在 Generic.getInteger 里。所以如果是对 Generic.getInteger 进行反汇编,可能就看不到里面的类型转换了。
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容