1

I know Generics are invariant: for any two distinct types Type1 and Type2, List< Type1> is neither a subtype nor a supertype of List< Type2>

so

List<someObject> nums = new ArrayList<someObject>(); // this is correct
List<Object> nums = new ArrayList<subObject>(); // this is  not correct

but

List<Number> nums = new ArrayList<Number>();
List<? super Number> sink = nums;   ????(line 2)

let say if wildcard is Object so line 2 wil be

List<Object> sink = List<Number> nums 

It seems that the invariant rule not applied here

can anyone explain to me why line 2 is compiled without error ?

Thank so much

das kinder
  • 1,180
  • 2
  • 10
  • 16
  • 3
    I'm not sure I understand what it is you're asking. The third line of code that you have isn't valid syntax. – Makoto Feb 15 '15 at 20:19
  • 2
    Take a look at [PECS](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs). – Boris the Spider Feb 15 '15 at 20:21
  • Can't tell what you're trying to ask. *"let say if wildcard is Object so line 2 wil be"* `List sink = List nums` This doesn't make any sense. – Radiodef Feb 15 '15 at 20:24
  • @Makoto The question is to explain how does this work: `List super Number> sink = new ArrayList() `?. I think it is a valid question – Jatin Feb 16 '15 at 10:46

3 Answers3

2

If I am not wrong, you wish to have an explanation on how is the below valid code:

List<Number> nums = new ArrayList<Number>();
List<? super Number> sink = nums;

Invariance is property of the class on how its type parameter affects its subtyping.

Generics are invariant, but wild cards exist to help us with with sub-typing. They are not very useful as they dont representing anytype but represent a good hack. Below is valid

List<Animal>  <: List<?>
List<?>       <: List

Better example:

List<? super Animal> d1= new ArrayList<Animal>();
d1.add(new Animal());
d1.add(new Dog());

The above works, because d1 is of type List<? super Animal>. You can imagine add function to behave like:

boolean add(? super Animal e);

So to add method you can pass any variable that is subtype of ? super Animal. And

Animal <: ? super Animal
Dog    <: ? super Animal

So adding a Dog or Animal works. So d1 acts as a list that can take any parameter of type Animal or subtype if it.

Similarly, you can also have below. But technically you cant add anything to this list. If there existed sometype in java that is subtype of every type, then you could properly add element of that type to it. Nothing Else.

ArrayList<? extends Animal> d1  = new ArrayList<Animal>();

Look at this answer for more info.

Community
  • 1
  • 1
Jatin
  • 31,116
  • 15
  • 98
  • 163
1

The invariant rule does indeed apply. The statement:

List<? super Number> sink = nums; 

just doesn't work they way you are thinking.

I expect that you think that you can assign an object of type ArrayList to a variable of type List<? super Number> because the former is a subclass of the latter. This would break the invariant rule, but this is not what is happening.

The List<? super Number> variable represents the set of all possible List where someClass is Number or is an ancestor of Number.

let say if wildcard is Object so line 2 wil be

     `List<Object> sink = List<Number> nums `

In this context the ? doesn't get set arbitrarily, so this doesn't happen.

Don Subert
  • 2,636
  • 4
  • 27
  • 37
-1

Lets have:

List<Integer> li = new ArrayList<>();
List<Object> lo = new ArrayList<>();
l = lo;//not allowed
lo.add("string");
Integer i = li.get(0);//that is string there

That is why you cannot make such assignment. I think compiler doesn't treat direct assignment of new ArrayList<Integer>() other then existing variable li.

Lech Głowiak
  • 366
  • 4
  • 8