Sun to Add Variance to Java in 1.5? 55
Ahe writes "I have been working on a joint project between
Sun Microsystems,
The University of Aarhus,
and The Alexandra Institute.
As you might know, Sun has for long been commited to
adding generics
to Java. Our project was to extend this with variance annotations for
more flexible typing of parameterized classes and arrays. Recently
Sun has released the project result as a
new prototype
with variance. If you like variance, please vote for this bug."
Somebody understood something ? (Score:2, Interesting)
Thanks
Re:Somebody understood something ? (Score:2, Informative)
covariance: CT: container ISA CQ: container iff T ISA Q; so you can assign each contained Q to a T inside a CT, i.e., Write a Superclass Value To The Subclass Container;
contravariance: CT ISA CQ iff Q ISA T; so you can assign some T from a Q in CQ, i.e., Read a Superclass Value From the Subclass Container;
bivariance or invariance: CQ ISA CQ iff Q ISA T and T ISA Q; basically, you can only read or write to/from some container Equivalent types (the same type, actually, in Java);
ok
Re:Somebody understood something ? (Score:3, Funny)
Thank you. (Score:2, Funny)
It's confusing, yes, but... it's not my fault. I just tried to make it more or less more more or less confusing!!
bye
Re:Thank you. (Score:1)
ahem. was that syntactic sugar in your tea?
</couldn't resist>
Re:Somebody understood something ? (Score:3, Informative)
And remember, if you vote on that bug you are NOT voting for generics. That has already been agreed upon. You are voting for adding "variance" to generics, which is explained in the parent post.
Re:Somebody understood something ? (Score:5, Informative)
Convariance means that, you can add a Derived to a list of Base without casting.
Contravariance means that you can unpack a Derived from a list of Base without casting.
Invariance is what you have in C++, where a list of Derived and a list of Base are two different things.
Re:Somebody understood something ? (Score:3, Informative)
Contravariance means that you can unpack a Base from a list of Derived without casting.
Re:Somebody understood something ? (Score:1, Funny)
Re:Somebody understood something ? (Score:1)
Re:Somebody understood something ? (Score:1, Interesting)
Features like these will only hasten the move towards dynamically typed languages like Python, Smalltalk, Ruby, and CLOS.
Dynamic typing may some dangerous, but the main thing that static typing prevents: calling a function that doesn't exist, happens in code about as often as dereferencing a null pointer. We don't see people shoveling syntax and stat
Definitely a bug! (Score:3, Insightful)
Generics are at best a trade-off: compile-time type safety in exchange for less readable code. A poor trade-off at best.
Java never has and never will suffer the catastrophic consequences of type casting that C++ can. Type casts are all subject to runtime checks, so that the worst possible result is that an exception will be thrown. Where C++ has no safety without generics, Java has runtime safety.
As for readability, C++ has two major benefits over Java: a preprocessor and typedefs. Without at least one of these features, generics make code almost unreadable. Little wonder that developers new to C++ are very cautious about getting involved with generics, or that old hands know how long it has taken for the STL to become mostly stable (I say mostly, because using STL with threads in cross-platform development is a recipe for disaster).
Java is starting to look very much like something designed by a committee. A pity, because at its core it is still a good thing.
Re:Definitely a bug! (Score:5, Interesting)
Maybe in the future I could just store them in a list and return that list because it is a string list specifically:
Re:Definitely a bug! (Score:3, Informative)
is not liked well by the Eclipse [eclipse.org] compiler because toArray(s) returns Object[]. Instead it prefers:
Re:Definitely a bug! (Score:1)
return (String[]) vector.toArray(new String[0]);
or even
private static final String dummy[] = {};
return (String[]) vector.toAyyar(MyClass.dummy);
Re:Definitely a bug! (Score:1)
Re:Definitely a bug! (Score:1)
toArray() will use the array given unless it's too small, so it's more efficient (and not any harder on the eyes or programmers fingers) to use an array of length vector.size().
Re:Definitely a bug! (Score:4, Informative)
You probably know this, but you usually don't want to return your internal list variable:
(I haven't looked at Java's proposed generics yet, so I don't know how that would look with generics. I think that you might have to cast the result of unmodifiableList since by default it returns a List of Objects, not a List of Strings.)
Re:Definitely a bug! (Score:2)
A List is a List, and it is modifiable. A new class, UnmodifiableList, which doesn't provide set() or add(), is the only answer.
Insightful? Come on! (Score:3, Insightful)
[rant]
about C++ casting (covariant model of generics): old-style casting was never of real use. use new_style_casts(x) and you have run-time checking, too. other stuff said about this is C++ ignorance.
[/rant]
ohboy, I had to get it off my chest.
Re:Insightful? Come on! (Score:2)
Re:Definitely a bug! (Score:4, Interesting)
The current release of jsr104 will even create mysterious ClassCastExceptions in some cases because the type inference is unsound. The documentation even warns of being able to do invalid casts (e.g. a String to a JFrame), which casts doubt on the safety of the complier. If that's the case, you can be sure that the jsr104 compiler is going to have one or more of its features axed before it makes it into tiger.
Re:Definitely a bug! (Score:2)
Wouldn't it be nice if any disallowed HTML were just passed through as literal text instead of being stripped out?
Re:Definitely a bug! (Score:2)
Foo<Bar> isn' a subtype of Foo (which in this context should be read Foo<Object>), is it? So why should it be a subclass?
That would require covariance in the type parameter implying subtyping, and a clear counter-argument is
void set_element(<param>). For Foo<Bar>, it accepts only Bar, but for Foo it accepts any Object. Thus, treating a Foo<Bar> as a Foo will cause runtime errors.
Java has already made this mistake with arrays.
They so should have done the Righ
Re:Definitely a bug! (Score:5, Interesting)
Given the choice between explicitly using a parameter, and using a nebulous "Object", I'd say that the template code is easier to read, because the parameter conveys more meaning than the word "object" (which offers no clue about what "type" is being used)
Where C++ has no safety without generics, Java has runtime safety.
Wrong. See dynamic_cast.
As for readability, C++ has two major benefits over Java: a preprocessor and typedefs
Shows how much you know -- you've named what are arguably two of the most botched legacy features of C++.
Without at least one of these features, generics make code almost unreadable.
This is not true. What makes code difficult to comprehend is complexity (allocaters, classes with several parametrised types, etc). Fortunately, C++ offers features that make complexity manageable (though typedefs don't deal with templates as well as they should)
(I say mostly, because using STL with threads in cross-platform development is a recipe for disaster
No, naively assuming that every STL implementation on every platform is thread safe is a recipe for disaster. Well, duh! The same is true even for straight C code -- you need to use thread safe versions of the library functions.
Generics more readable (Score:5, Interesting)
When using non-generic containers in Java, you are usually forced to make a cast when accessing its members. For example:
String s = (String) list.get(0);
It gets worse if you are making multiple calls, because you usually need parentheses to bind the cast:
String s = ((Foo) list.get(0)).fooMethod();
However, with generics, you don't have to write the cast, because the type is implied. The bytecode is the same, but the code is much clearer:
String s = list.get(0).fooMethod();
Tell me how that is less readable. Anybody who thinks generics are unreadable is probably thinking of the worst C++ template abuses, needless complexity, and obscure syntax. Thankfully, Java generics are simple and clear.
Re:Definitely a bug! (Score:3, Insightful)
In C++, the reason people are scared of templates is that they're actually quite complicated, with historical stability problems and continuing unexpected behavior. Java only supports the more obvious cases.
Java has been designed by committee from the start, but it's always been an extremely conservative committ
Variance? (Score:3, Funny)
Re:Variance? (Score:4, Informative)
Say you have a List, and you want to do:
Number num = list.get(0);
In this case, you need to know that the list contains elements which are Number or a subtype of Number, so you declare that you're taking a List<+Number>
If you want to put a Number into the list, you need to know that the list can contain Numbers, which means that it has to be a list of "at most" Numbers (i.e., it is not a List of something more specific, which would not accept a Number). You thus declare that you're taking a List<-Number>.
If you're going to do both, you require that the list contain nothing that's not a Number and that it be able to contain anything that is a Number, so you declare it to be List<=Number> (the = is optional in this case).
If you don't care what type the elements are, you can use List<*>, rather than the equivalent List<+Object> (a list which contains Objects and subtypes; unrestrictive, since everything that's not a primitive type is a subtype of Object). This is somewhat clearer, since it means that you don't care at all.
Of course, actual code is more likely to use type variables rather than Number; sort(), for instance, takes a List which is exactly of some unspecified type and a Comparator which does not require anything more specific than that type.
Variance is a neat idea, but what's the rush? The issue is dealing with arrays. Traditional arrays require that a variable of Number[] get a value of at least Number[] (i.e., +Number in the new syntax), but they allow you to store a Number in the array, even if the array is actually of a subtype of Number; if it doesn't fit, you get a runtime exception. However, the extra type information for generics isn't around at runtime, so nothing can stop a List<Number> from being stored into an array of List<Double> which has been passed into a method which takes an array of Object (at compile time, it is an array of Object getting a List<Number>, at runtime, it is an array of List getting a List, but then a[0].get(0) might be an Integer not a Double like it's supposed to be). So the idea is to get a version of arrays like the variance-using Lists above into the language to be used with generics, which implies including variance at the same time as generics, so that unsafe arrays mixed with generics can be prohibited.
Re:Variance? (Score:1)
Not you -- the compiler would need to know. Like with all parametric polymorphism of this kind, it is all about moving type correctness checks from runtime to compile time.
What confuses me is that they are adding variable arguement lists. Why?
As far as
Re:Variance? (Score:2)
Generics aren't at all the same as C++ templates, although they draw on C++ experience to avoid the C++ problems, like most of Java. This is like how Java includes single in
What is variance? (Score:5, Informative)
From http://forum.java.sun.com/thread.jsp?forum=316&thr ead=389987&start=15&range=15&tstart=0&trange=1 5 [sun.com]:
> I can't quite get my head round what combination of // legal // illegal
> VM, compiler and/or language changes would iron out
> the following incompability between arrays and
> generics:
>
> Cat[] cats = new Cat[10];
> Animal[] animals = cats;
>
> List cats = new List(10);
> List animals = cats;
> according to JSR-14
This problem is addressed in the "variance" extension to
the generic type system, which will be included in the
imminent JSR14 prototype 2.0. Details are enclosed in
the prototype.
Also a link to a MIT research paper on variance [mit.edu] from that thread.
Re:What is variance? (Score:2)
Given animals aliased to cats, it would be statically type safe for me to say animals[0]=new Dog();. But this causes a runtime error. Runtime errors on assignment!?! Array subtyping is NOT a feature (although I would have to think for a bit what to replace it with before removing it).
Re:What is variance? (Score:1)
In which case assigning an array of Cats to animal is a static type error:
Or you can declare it to be covariant in a statically checked way, by writing:
Relation to covariant return types? (4144488) (Score:2)
How does this bug relate, technically, to RFE 4144488 [sun.com], which is pretty high on the vote count already? It seems they are requesting pretty similar stuff, so I'm curious if this is a tactical move to ensure the tiger is variant. Should we vote for both, or just this one?
I want both of them, anyway. Good luck.
Re:Relation to covariant return types? (4144488) (Score:3, Informative)
return types on methods, this is for
covariant (and contravariant) generic type
parameters.
Short description of variance (Score:5, Informative)
+ 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.
Re:Short description of variance (Score:1)
Re:Short description of variance (Score:1, Troll)
Re:Short description of variance (Score:1)
So if I understand this correctly, you were able to avoid the JVM changes that seemed to implied by the previous prototype, by using annotations instead.
I think this is great news. Do you think youll get it through the business decision paper mill in time for Tiger?
Re:Short description of variance (Score:1)
Try programming with generics, but without variance, and you will see what I mean.
Re:Links don't work! (Score:1)
It's free registration. Just like the NY Times. But yeah, I hate the NY Times links...keep forgetting my login.
Links (Score:2, Informative)
There is a discussion about this on Lambda the Ultimate [weblogs.com].
These links don't require registration :-)
Variance homepage (Score:1)
Reinventing The Wheel (Again) (Score:1)