← Back to Users
Ahe's activity in the archive.
We're looking into it: 5072831
No changes to the JVM were necessary for the previous release. What variance does to generics is adding the flexibility that programmers would expect IMHO. Try programming with generics, but without variance, and you will see what I mean.
The term variance covers co-variance, contra-variance, and bi-variance. In the 1.5 prototype you can use variance annotations on parameterized types. + means co-variant (think read-only).- means contra-variant (think write-only).* mean bi-variant (niether read nor write). You are familiar with co-variance from arrays in Java. When an array of Integer is a subtype of array of Number, arrays are said to be covariant in their element type. Consider: Number[] ns = new Integer[10]; With generics, you can have a list of Numbers: List<Number> nl = new List<Number>(); However, since generics are added without changing the JVM, nl can only refer to lists of exactly Number, e.g., this is wrong: List<Number> nl = new List<Integer>(); So why is this wrong, consider arrays: Number[] ns = new Integer[10];ns[0] = new Double(0.0); // run-time error Since ns refers to an array of Integer, we cannot put Double in to it. The mechanism that catches this is called store-check. Since the JVM is not modified, we cannot implement a store-check for generic classes. Variance annotations allows us more flexibility, however. Consider this method: void copy(Collection<+Number> src, Collection<-Number> dst) { for (Number n : src) { dst.add(n); }} Here we use variance annotations to state that we will only read from src and only write to dst. In this way we are allow to make a call like this: List<Integer> il = new List<Integer>();List<Object> ol = new List<Object>();copy(il, ol); Sometimes we are not interested in reading or writing elements, so we can say: List<*> list_of_unknown_type = ...; Then we can only use methods like size() on list_of_unknown_type.
We're looking into it: 5072831
No changes to the JVM were necessary for the previous release. What variance does to generics is adding the flexibility that programmers would expect IMHO.
Try programming with generics, but without variance, and you will see what I mean.
The term variance covers co-variance, contra-variance, and bi-variance. In the 1.5 prototype you can use variance annotations on parameterized types.
// run-time error
...;
+ means co-variant (think read-only).
- means contra-variant (think write-only).
* mean bi-variant (niether read nor write).
You are familiar with co-variance from arrays in Java.
When an array of Integer is a subtype of array of Number, arrays are said to be covariant in their element type. Consider:
Number[] ns = new Integer[10];
With generics, you can have a list of Numbers:
List<Number> nl = new List<Number>();
However, since generics are added without changing the JVM, nl can only refer to lists of exactly Number, e.g., this is wrong:
List<Number> nl = new List<Integer>();
So why is this wrong, consider arrays:
Number[] ns = new Integer[10];
ns[0] = new Double(0.0);
Since ns refers to an array of Integer, we cannot put Double in to it. The mechanism that catches this is called store-check.
Since the JVM is not modified, we cannot implement a store-check for generic classes. Variance annotations allows us more flexibility, however.
Consider this method:
void copy(Collection<+Number> src, Collection<-Number> dst) {
for (Number n : src) { dst.add(n); }
}
Here we use variance annotations to state that we will only read from src and only write to dst. In this way we are allow to make a call like this:
List<Integer> il = new List<Integer>();
List<Object> ol = new List<Object>();
copy(il, ol);
Sometimes we are not interested in reading or writing elements, so we can say:
List<*> list_of_unknown_type =
Then we can only use methods like size() on list_of_unknown_type.