Java 数组协方差是否违反 Liskov 替换原则?

Lee*_*ang 5 generics language-design liskov-substitution-principle covariance solid-principles

我正在阅读为什么 Java 中的数组协变很糟糕(为什么数组协变而泛型是不变的?)。如果 aDog是 的子类型Animal,则 aDog[]是 的子类型Animal[]。这是一个问题,因为可以这样做:

Animal[] animals = new Dog[1];
animals[0] = new Cat();
Run Code Online (Sandbox Code Playgroud)

这与“正确”实现的泛型不同。AList<Dog>不是的子类型List<Animal>

我试图理解为什么它不好的本质,并且刚刚阅读了 LSP。它是否以任何方式违反了 LSP?似乎没有明显的违规行为。

sep*_*p2k 6

它是否以任何方式违反了 LSP?

是的。

似乎没有明显的违规行为。

你自己的例子是违规的。以下代码工作正常:

Animal[] animals = new Animal[1];
animals[0] = new Cat();
Run Code Online (Sandbox Code Playgroud)

但是如果现在Animal[]用它的子类型替换Dog[],代码将不再起作用(也就是说,它会导致以前没有的异常)。因此该类型Dog[]不能在任何可以使用其超类型Animal[]并且违反 LSP 的地方使用。

把这放在 LSP 的措辞中:如果我们考虑属性“new Cat()可以作为元素分配”,则类型Animal[]满足此属性,但其子类型Dog[]不满足。