35

The below line gives me error :

Incompatible Types.

List<List<Integer>> output = new ArrayList<ArrayList<Integer>>();

What is the reason?

EDIT

I understand if I change my second ArrayList to List, it does not give me error. I want to know the reason of error though. Thanks

Kraken
  • 20,468
  • 32
  • 90
  • 145

6 Answers6

33

From Generics, Inheritance, and Subtypes

This is a common misunderstanding when it comes to programming with generics, but it is an important concept to learn.

enter image description here

Box<Integer> is not a subtype of Box even though Integer is a subtype of Number.

Community
  • 1
  • 1
earthmover
  • 4,039
  • 10
  • 42
  • 73
  • This doesn't answer the question. The question is "what is the reason?". All you've done is restate the question's premise, using different classes. – Dawood ibn Kareem Aug 09 '20 at 23:06
29

If you had a List<List<Integer>> then you'd be able to add a LinkedList<Integer> to it. But you can't do this for an ArrayList<ArrayList<Integer>>, so the latter can't possibly be a type of List<List<Integer>>.

Dawood ibn Kareem
  • 68,796
  • 13
  • 85
  • 101
27

The correct writing should be: List<List<Integer>> ret = new ArrayList<List<Integer>>(); Since in this way, you can add not only ArrayList but also LinkedList to ret

spiralmoon
  • 2,512
  • 1
  • 21
  • 25
9

The reason is that generics are not covariant.

Consider simpler case:

List<Integer> integers = new ArrayList<Integer>();
List<Number> numbers = integers; // cannot do this
numbers.add(new Float(1337.44));

Now List holds a Float, which is certainly bad.

Same for your case.

List<ArrayList<Integer>> al = new ArrayList<ArrayList<Integer>>();
List<List<Integer>> ll = al; // cannot do this
ll.add(new LinkedList<Integer>())

Now you have a list ll which holds LinkedList, but the al is declared as a List of ArrayLists.

lpiepiora
  • 13,246
  • 1
  • 33
  • 45
6

It is clearly stated in Java Doc

In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G<Foo> is a subtype of G<Bar>. This is probably the hardest thing you need to learn about generics, because it goes against our deeply held intuitions.

Same thing happens here it's Bar = List<Integer> and Foo = ArrayList<Integer> as ArrayList<ArrayList<Integer>> is not sub type of List<List<Integer>>

ΔȺȾΔ
  • 21,571
  • 10
  • 52
  • 80
3

Less text more fixes:

List<List<Integer>> lists = new ArrayList<>();

or

List<List<Integer>> lists = new ArrayList<List<Integer>>();
Pavel Shkleinik
  • 6,050
  • 2
  • 20
  • 35