-1

So, let's say i have a simple list if Integers:

List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
// intList.add("zxc"); // this will obviously fail

Now let's wrap the list inside another list:

List<List<Integer>> listOfListOfInt = new ArrayList<>();
listOfListOfInt.add(intList);

It's all fine. Now let's create the method

private static void method1(List<? extends List> cont) { // [1]
    List<? super Date> data = cont.get(0);  // [2]
    data.add(new Date());
}

Basically i'm adding DATE to the first list in the list, because i'm telling it to treat that list as List<? super Date>. And it works because of the type erasure, of course:

    method1(listOfListOfInt);
    System.out.println(intList);

prints [1, 2, Tue Jun 14 23:41:15 BST 2016], so my List<Integer> now has a Date in it.

Now i understand what's going on, because of the type erasure the List<? extends List> becomes just a List, and then it's up to me what to put in it, so i'm putting Date.

Now the question i don't quite understand is that why there is no warning of "Unchecked assignment/calls" at all? According to the java compiler that code is perfectly type safe?

It will give the warning if in the method1 you'll replace List<? extends List> to just a List<List> for example, or if you'll replace List<? super Date> with just a List, and so on, generally you'll be warned about unchecked assignments/calls. But in this case you won't, all is fine.

UPDATE: Apparently there's warning by the compiler, but Intellij Idea refuses to show it for some reason. I have "Unchecked warning" inspection set without ignoring anything. And all settings are defaults anyway i think.

IntelliJ IDEA 2016.1.3 Build #IC-145.1617, built on June 3, 2016 JRE: 1.8.0_77-b03 x86 JVM: Java HotSpot(TM) Server VM by Oracle Corporation

Update2: it's not a duplicate, as the question is not about the functionality of raw types but about the lack of warning in this particular case. And it turns out it's just an IDE quirk.

Eugene
  • 345
  • 1
  • 4
  • 14
  • 2
    I get a warning. How do you compile your code? – Sotirios Delimanolis Jun 14 '16 at 22:49
  • This has to do with backward compatibility more than erasure. Why is it easy to blame erasure for everything? – Sleiman Jneidi Jun 14 '16 at 22:52
  • 1
    Your problem is that the second `List` in the type `List extends List>` is *raw*. Raw is not the same as *erasure*. Raw loses type safety, erasure doesn't. Your IDE(!) should have warned you about the raw use of a generic. – Andreas Jun 14 '16 at 22:54
  • I'm not "blaming" type erasure, it's working as expected. I'm just puzzled that there are no warnings in this case. – Eugene Jun 14 '16 at 22:55
  • So where's warning that i'm converting generic type into the raw type then? Note that it GIVES a warning if instead of `List extends List>` you're using slightly different RAW type `>`. – Eugene Jun 14 '16 at 22:56
  • It should be `List extends List> cont`; no converting here at all. – Mordechai Jun 14 '16 at 22:57

1 Answers1

1

Your issue is the use of a raw type in this declaration: List<? extends List>. The second List is raw. Your issue has nothing to do with type erasure.

When entering the following code in Eclipse, I get warnings.

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        intList.add(1);
        intList.add(2);
        List<List<Integer>> listOfListOfInt = new ArrayList<>();
        listOfListOfInt.add(intList);
        method1(listOfListOfInt);
        System.out.println(listOfListOfInt);
    }
    private static void method1(List<? extends List> cont) { // [1]
        List<? super Date> data = cont.get(0);  // [2]
        data.add(new Date());
    }
}

Warnings from Eclipse

[1] List is a raw type. References to generic type List<E> should be parameterized
[2] Type safety: The expression of type capture#1-of ? extends List needs unchecked conversion to conform to List<? super Date>

When compiling with jdk1.8.0_91, I get:

Note: Test.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Adding -Xlint:unchecked, I get:

Test.java:17: warning: [unchecked] unchecked conversion
                List<? super Date> data = cont.get(0);  // [2]
                                                  ^
  required: List<? super Date>
  found:    CAP#1
  where CAP#1 is a fresh type-variable:
    CAP#1 extends List from capture of ? extends List
1 warning

As you can see, you have been warned, both by the IDE (Eclipse in my case) and by the Java compiler.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Intellij Idea doesn't give me any warning in this case, but you're right - i've just tried to compile it manually and it does have the warning which makes sense. So i guess some obscure flag somewhere in settings for Idea is unset, although i can't find where. It's very weird. – Eugene Jun 14 '16 at 23:16