java - 为什么 Bounded 类型参数出现 "java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to"错误而不是 Formal 类型参数?

标签 java generics classcastexception

由于 java 没有通用数组,我使用了将对象数组转换为类型参数的常规技巧。当我有一个像 <T> 这样的正式类型参数时,这工作正常但当我使用有界类型参数时不是 <T extends something> .

以下使用正式类型的代码工作正常

public class Deck <T> {
    private T [] cards;
    private int size;

    public Deck () {
        cards = (T []) new Object[52];
        size = 0;
    }
}

public class BlackJackGame {
    Deck<BlackJackCard> deck;

    public BlackJackGame() {
        deck = new Deck<>();
        populate (deck);
        deck.shuffle();
    }
}

public class BlackJackCard extends Card {
}

以下使用有界类型的代码会抛出错误

public class Deck <T extends Card> {
    private T [] cards;
    private int size;

    public Deck () {
        cards = (T []) new Object[52];
        size = 0;
    }
}

public class BlackJackGame {
    Deck<BlackJackCard> deck;

    public BlackJackGame() {
        deck = new Deck<>();
        populate (deck);
        deck.shuffle();
    }
}

public class BlackJackCard extends Card {
}
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LCard;
    at Deck.<init>(Deck.java:10)
    at BlackJackGame.<init>(BlackJackGame.java:5)

最佳答案

这个例子让我想起了早年,当我在“Effective java”一书中阅读泛型时......

首先,这是 Java 泛型的黄金法则:不要混合使用数组和泛型,因为这样很可能会产生不安全的代码。 您的代码混合了泛型(例如 T、T extends Card)和数组(例如 T [] cards)。然后,你在运行时得到了不安全的代码。

这是一种安全的方式(优先使用列表而不是数组):

class Deck <T extends Card> {
    private List<T> cards;

    public Deck () {
        cards = new ArrayList()<>;
    }

现在,要回答您的问题,您应该先回到 java 中的一些基础知识:

1- 数组是共变结构

2- 泛型是不变的构造

3-元素类型在数组中具体化(具体化)

4- Parameter Type 在Generic中被删除(Type erasure)

别担心,抛开可怕的概念,看看你的例子发生了什么:

  • 正式类型 T 在运行时被删除。

  • 这意味着它在字节码中被完全删除。

  • 在第一个例子中,T 被替换为 Object,因为它是离它最近的类(在继承方面) 所以,

cards = (T []) new Object[52]

翻译成

cards = (Object []) new Object[52];

这是安全的。

  • 在第二个示例中,T 绑定(bind)到 Card,因此它成为最接近它的类(在继承方面) 所以,
cards = (T []) new Object[52]

翻译成

cards = (Card []) new Object[52];

由于 Object 不是 Card 的子类型,因此您会遇到运行时转换异常。

关于java - 为什么 Bounded 类型参数出现 "java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to"错误而不是 Formal 类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58036163/

相关文章:

Java 获取焦点窗口

Java8 相当于 JodaTime DateTimeFormat.shortDate()

java.lang.NoClassDefFoundError : org/apache/log4j/PropertyConfigurator 错误

java - Collections 实用程序类中排序函数的实现比较

java - Java 中的 ClassCastException

java - 如何在 groovy 中列出 JVM 中的所有(groovy)类

Java 泛型接口(interface)返回泛型

delphi - 如何释放通用 TList<T>?

java - Android - 应用程序崩溃并显示 "java.lang.ClassCastException"

java - 类 Cast Exception Generics Reflection ParameterizedType