Covariance and Invariance
About
Covariance and invariance are concepts in type systems that describe how types relate to each other in the context of inheritance or generic typing.
Covariance
Covariance allows a child type (Subclass
) to be used where a parent type (Superclass
) is expected. It maintains the "is-a" relationship.
Example: Covariance in Arrays
In Java, arrays are covariant. This means an array of a subtype can be assigned to an array of its supertype.
Potential Runtime Exceptions: While covariance allows this assignment, it is unsafe:
Why? At runtime, the JVM enforces that the array actually contains String
elements.
Covariance in Generics
Generics in Java support covariance using wildcards (? extends T
).
? extends Number
means "a list of some subtype ofNumber
".We can read elements as
Number
, but we cannot add elements, as the exact subtype is unknown.
Invariance
Invariance means that a type and its subtypes are not interchangeable. This is stricter than covariance.
Example: Invariance in Generics
In Java, generic types are invariant. This means a List<String>
is not a subtype of List<Object>
, even though String
is a subtype of Object
.
Why? If this were allowed, it would break type safety:
Comparison Table
Aspect
Covariant
Invariant
Definition
Subtypes can be used where supertypes are expected.
Types are not interchangeable, even with subtyping.
Example
String[]
can be assigned to Object[]
.
List<String>
cannot be assigned to List<Object>
.
Flexibility
More flexible but less type-safe.
Stricter but safer.
Usage in Java
Arrays (T[]
) are covariant.
Generics (List<T>
) are invariant.
Last updated
Was this helpful?