Search code examples
genericscovariancelanguage-designsolid-principlesliskov-substitution-principle

Does Java array covariance violate Liskov Substitution Principle?


I was reading why array covariance in Java is bad (Why are arrays covariant but generics are invariant?). If a Dog is a subtype of Animal, then a Dog[] is a subtype of Animal[]. This is a problem because things like this can be done:

Animal[] animals = new Dog[1];
animals[0] = new Cat();

This is different from generics which were implemented 'correctly'. A List<Dog> is not a subtype of List<Animal>

I was trying to understand the essence of why it is bad and had just read about LSP. Did it violate the LSP in any way? There doesn't seem to be a clear violation.


Solution

  • Did it violate the LSP in any way?

    Yes.

    There doesn't seem to be a clear violation.

    Your own example is a violation. The following code works fine:

    Animal[] animals = new Animal[1];
    animals[0] = new Cat();
    

    But if now replace the Animal[] with its subtype Dog[], the code no longer works (that is, it causes an exception when it didn't previously). So the type Dog[] can't be used everywhere where its supertype Animal[] can be used and that violates the LSP.

    To put this in the LSP's wording: If we consider the property "new Cat() can be assigned as an element", the type Animal[] fulfils this property, but its subtype Dog[] does not.