'Invariant Generics don't seem working correctly
I've read some articles about Covariance, Contravariance, and Invariance in Java, but I'm confused about them.
I'm using Java 11, and I have a class hierarchy A => B => C (means that C is a subtype of B and A, and B is a subtype of A) and a class Container:
class Container<T> {
public final T t;
public Container(T t) {
this.t = t;
}
}
for example, if I define a function:
public Container<B> method(Container<B> param){
...
}
here is my confusion, why does the third line compile?
method(new Container<>(new A())); // ERROR
method(new Container<>(new B())); // OK
method(new Container<>(new C())); // OK Why ?, I make a correction, this compiles OK
if in Java Generics are invariant.
When I define something like this:
Container<B> conta = new Container<>(new A()); // ERROR, Its OK!
Container<B> contb = new Container<>(new B()); // OK, Its OK!
Container<B> contc = new Container<>(new C()); // Ok, why ? It's not valid, because they are invariant
Solution 1:[1]
Covariance is the ability to pass or specify a subtype when a supertype is expetced. If your C class extends B, then C is a child class of B. This relationship between C and B is also called is-a relationship, where an instance of C is also an instance of B. Therefore when your variable contc is expecting a B instance and you're passing new C(), since new C() is an instance of C and C instance is (also)-an instance of B, then the compiler allows the following writing:
Container<B> contc = new Container<>(new C());
Conversely, when you're writing
Container<B> conta = new Container<>(new A());
you're receiving an error because A is a supertype of B, there is no is-a relationship from A to B, but rather from B to A. This is because every instance of B is also an instance of A, but not every instance of A is an instance of B (To make a silly example, every thumb is a finger but not every finger is a thumb). A is a generalization of B; therefore it cannot appear where a B instance is expected.
Here there's a good article expanding the concept of covariance in java.
Solution 2:[2]
The question's examples don't demonstrate the invariance of generics.
An example which does demonstrate this would be:
ArrayList<Object> ao = new ArrayList<String>(); // does not compile
(You might incorrectly expect the above to compile, because String is a subclass of Object.)
The question shows us different ways to construct Container<B> objects - some of which compile and others which do not, because of the inheritance hierarchy of A, B and C.
That diamond operator <> means that the created container is of type B in every case.
If you take the following example:
Container<B> contc = new Container<>(new C()); // compiles
And re-write it by populating the diamond with C, the you will see that the following does not compile:
Container<B> contc = new Container<C>(new C()); // does not compile
That will give you the same "incompatible types" compilation error as my ArrayList example.
Solution 3:[3]
order placed is order placed.
Anything happened after, eg. price, quantity, cannot modify.
You can cancel the order, create a new order manually with different quantity within Shopify Admin.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | andrewJames |
| Solution 3 | Charles C. |
