Showing posts with label type system. Show all posts
Showing posts with label type system. Show all posts
18 May 2019
Thoughts on Type Variance
in Java arrays are covariant (can be assigned to an array of supertype)
Integer[] arr = {1, 2, 3};
Object[] objArr = arr; // allowed because of being covariant
objArr[0] = "Hello"; // runtime error: ArrayStoreException
But it comes at a cost that, it might fail at runtime (as in the last line)
in Kotlin, arrays are invariant:
val arr = arrayOf(1, 2, 3)
val objArr: Array<Any> = arr // compilation error
So, invariant, doesn't consider List<Integer> to substitue List<Object> nor vice versa,
However, covariant consider List<Integer> to substitue List<Object>, but not vice versa.
And contravriant consider List<Object> to substitude List<Integer>, but not vice versa.
in Kotlin, Lists (immutable lists) are covariant, the following works:
val list = listOf(1, 2, 3)
val objList: List<Any> = list
because Lists are immutable, we can't fail as in the Java array case.
in contravariant, the super type can substitute the subtype (might seems illogical at first),
but look at this (fiction example):
operateOnIntegers(Integer i) {
i.setValue(50)
}
Number n = 30
operateOnIntegers(n)
because operateOnIntegers expected a narrower type than the passed one (expects Integer and passed Number),
it will never write a value into it that exceeds its limits.
22 January 2015
Two notes about Java Generic Types (Type Covariance and Type erasure)
Java Generics have two characteristics that are important when working with generics of Java.
The first one is the most important and most well-known than the other, the second is less known.
However in case of Generic types, such error is being caught at compile time, and this is because Type Parameters (Generics) doesn't allow type covariance.
Example:
The first one is the most important and most well-known than the other, the second is less known.
1. Generics types are not Covariant:
All of us knows that List<String> cannot substitute List<Object>; however String[] can substitute Object[]
This prevent error in Generics that happens in case of arrays.
String[] sArr = new String[] {"Hello"};
Object[] oArr = sArr;
oArr[0] = 10; // << Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer
Example:
List<String> sList = new ArrayList<>();
List<Object> oList = sList; // Type mismatch: cannot convert from List<String> to List<Object>
oList.add(10);
2. Type parameters is being removed in generated byte code (Called Type erasure).
This is why you cannot say: T.class
Quote:
When you compile some code against a generic type or method, the compiler works out what you really mean (i.e. what the type argument forT
is) and verifies at compile time that you're doing the right thing, but the emitted code again just talks in terms ofjava.lang.Object
- the compiler generates extra casts where necessary. At execution time, aList<String>
and aList<Date>
are exactly the same; the extra type information has been erased by the compiler.
Find more here: http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java
Subscribe to:
Posts (Atom)