I encountered a problem at work, described in code as follows:
1 2 3 4 5 6 7 8 9 10 11 |
|
You need to write a function func here, which can take the list of Base as a parameter. I thought it was okay to pass a Derived list, because Derived is a derived class of Base, so Derived's list should also be a derived class of Base's list, but the compiler reported an error.
To find out the reason, I checked some information on the Internet: Java's generics are not covariant.
Covariance and contravariance of generics are both terms. The former refers to the ability to use a type that is less derived (less specific) than the originally specified derived type, and the latter refers to the ability to use a derived type that is smaller than the originally specified derived type. A more derived (more specific) type.
For example, generics in C# support covariance:
1 2 |
|
But Java’s generics do not support covariance. Code similar to the above cannot be compiled in Java.
But interestingly, arrays in Java support covariance, for example:
1 2 |
|
Summary: Java's generics do not support covariance, and it is more from the perspective of type safety. This design is not necessarily necessary. For example, C# does not use this design. It can only be said that the designers of Java made a choice between ease of use and type safety.
Finally, back to the original question, to implement such a method func, you can modify it to:
1 2 |
|
or use a parameterized type:
1 2 |
|
But this also has problems, it will blur the parameter type of func. A better way is not to change func, but to pass a Base type List when passing parameters, which requires converting elements to Base type when adding them to the List.
PS: By limiting the parameter type:
1 2 |
|