Hacker News new | ask | show | jobs
by charcircuit 1145 days ago
If you covariance, it's the first example because String is a subtype of Object. List is the same thing as List<Object>.

The first example is missing some parenthesis, but it should convoy my point.

1 comments

Assuming we are talking about java, List is not the same as List<Object>.

List<Object> list = new ArrayList<String>(); will fail to compile.

Generic types in Java have no variance by default. The only type that can be assigned to List<String> is exactly List<String>.

Your example would want to be List<? extends Object> foo = new List<String>();

There is a reason for this. Consider:

  List<String> foo;
  List<Object> bar = foo;
  bar.add(new Integer(0));
If the above works, you would be adding an Integer to a collection of Strings, which is not sound.

In general, you typically want to be covarient in type parameters that are used for arguements, and contravariant in type parameters that are used for return values. In the general case, this is unworkable (since types parameters are often used for both), so the only reasonable behaviour is to be invariant.

Raw arrays in Java are actually covariant - which is not reasonable - and quickly result in a runtime type exception when you get to the "bar[0] = new Integer(0)" portion of the above example.

Scala allows you to explicitly mark type parameters as covariant or contravariant, as bellow:

    class Foo[+T] //Foo is covariant in T
    class Foo[-T] //Foo is contravarient in T
    class Foo[T]  //Foo is invarient in T
However, no equivelent mechanism exists in Java.