Slashdot Mirror


Sun to Add Variance to Java in 1.5?

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."

11 of 55 comments (clear)

  1. Re:Somebody understood something ? by hummassa · · Score: 2, Informative

    kind of simple, really...

    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? hope to have helped;

    Massa

    --
    It's better to be the foot on the boot than the face on the pavement. ~~ tkx Kadin2048
  2. What is variance? by DeadSea · · Score: 4, Informative
    I've done some googling and I've come up with some quick answers. It seems it makes Java generics act more like C++ Collections in some cases.

    From http://forum.java.sun.com/thread.jsp?forum=316&thr ead=389987&start=15&range=15&tstart=0&trange=1 5:

    > I can't quite get my head round what combination of
    > VM, compiler and/or language changes would iron out
    > the following incompability between arrays and
    > generics:
    >
    > Cat[] cats = new Cat[10];
    > Animal[] animals = cats; // legal
    >
    > List cats = new List(10);
    > List animals = cats; // illegal
    > 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 from that thread.

  3. Re:Somebody understood something ? by Hard_Code · · Score: 2, Informative

    Why was this modded funny? This was the explanation of variants that was necessary.

    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.

    --

    It's 10 PM. Do you know if you're un-American?
  4. Re:Relation to covariant return types? (4144488) by gafter · · Score: 3, Informative

    No relation at all. That is for covariant
    return types on methods, this is for
    covariant (and contravariant) generic type
    parameters.

  5. Re:Somebody understood something ? by be-fan · · Score: 4, Informative

    En anglias:

    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.

    --
    A deep unwavering belief is a sure sign you're missing something...
  6. Short description of variance by Ahe · · Score: 5, Informative

    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.

  7. Re:Somebody understood something ? by fizbin · · Score: 2, Informative

    Minor correction:

    Contravariance means that you can unpack a Base from a list of Derived without casting.

  8. Re:Definitely a bug! by rlowe69 · · Score: 2, Informative
    I don't know what compiler you are using, but your example

    public String[] getStrings(){
    String[] s = new String[vector.size()];
    return vector.toArray(s);
    }
    is not liked well by the Eclipse compiler because toArray(s) returns Object[]. Instead it prefers:

    public String[] getStrings(){
    String[] s = new String[vector.size()];
    return (String[])vector.toArray(s);
    }
    --
    ----- rL
  9. Re:Definitely a bug! by j7953 · · Score: 3, Informative

    You probably know this, but you usually don't want to return your internal list variable:

    public List getStrings() {
    return Collections.unmodifiableList(list);
    }

    (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.)

    --
    Sig (appended to the end of comments I post, 54 chars)
  10. Re:Variance? by iabervon · · Score: 3, Informative

    Nope, actually "Variance". The idea is that sometimes you need to know that something is exactly of some type, sometimes you need to know that something is "at least" of some type (i.e., equal or a subtype), and sometimes you need to know that something is "at most" of some type.

    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.

  11. Links by bonniot · · Score: 2, Informative
    The research article presenting the theory of variance.

    There is a discussion about this on Lambda the Ultimate.

    These links don't require registration :-)