java - java.lang.Object 的泛型不能转换为 [Ljava.lang.Object

标签 java generics classcastexception generic-list

谁能解释为什么通用 <Object[]>导致 ClassCastException (运行时异常!)

我知道在编译阶段删除所有泛型并且对字节码没有任何影响。但它似乎有一些细微差别。

这是我的例子(为这篇文章做了简化):

public class CastTest {
    public static void main(String[] args) {
        List a = new ArrayList();
        a.add(new Object());
        List<Object[]> b = a;
        b.get(0).toString();
    }
}

此代码返回:

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to [Ljava.lang.Object;
    at CastTest.main(CastTest.java:9)

我不明白这段代码有什么问题。有人可以解释这种行为吗?

最佳答案

您是在告诉编译器您要调用 Object[].toString()。这就是编译器生成强制转换 (checkcast) 的原因:

 0: new           #2                  // class java/util/ArrayList
 3: dup
 4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
 7: astore_1
 8: aload_1
 9: new           #4                  // class java/lang/Object
12: dup
13: invokespecial #1                  // Method java/lang/Object."<init>":()V
16: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: checkcast     #7                  // class "[Ljava/lang/Object;"
34: invokevirtual #8                  // Method java/lang/Object.toString:()Ljava/lang/String;
37: pop
38: return

您可以通过在 Java 代码中自己添加强制转换来防止字节码强制转换:

public static void main(String[] args) {
    List a = new ArrayList();
    a.add(new Object());
    List<Object[]> b = a;
    ((Object) b.get(0)).toString();
}

现在编译器发现不需要转换为 Object[],因为您只需要一个 Object 引用。 checkcast 操作码被省略:

 0: new           #2                  // class java/util/ArrayList
 3: dup
 4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
 7: astore_1
 8: aload_1
 9: new           #4                  // class java/lang/Object
12: dup
13: invokespecial #1                  // Method java/lang/Object."<init>":()V
16: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: invokevirtual #7                  // Method java/lang/Object.toString:()Ljava/lang/String;
34: pop
35: return

关于java - java.lang.Object 的泛型不能转换为 [Ljava.lang.Object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29509135/

相关文章:

java - 如何使用java远程写入文件

java - 实例化使用 <Foo extends Bar<Foo>> 的通用对象

typescript - TypeScript 中必需的与推断的泛型类型

c# - 查找具有不同类型值的两个字典的并集

android - java.lang.ClassCastException : android. app.ContextImpl 错误

java - 如何解决 HibernateTemplate 的 findByCriteria() 中的类转换异常?

java - 覆盖 wildfly/jboss 模块中特定 java 类文件的类加载

java - 为什么 Hudson 忽略我的 profiles.xml 文件?

java - 如何正确使用单选按钮?

eclipse - 无法将Eclipse项目转换为IJavaProject