Search code examples
javagenericstype-erasureuncheckedraw-types

Unchecked assignment warning


I am using Android Studio 1.1.0.

This causes no warning:

public static class A {
    public Map<Integer, String> getMap() {
        return null;
    }
}

public static class B {
    public void processA(A a) {
        Map<Integer, String> map = a.getMap();
    }
}

But make A generic:

public static class A<T> {
    public Map<Integer, String> getMap() {
        return null;
    }
}

And this line:

Map<Integer, String> map = a.getMap();

gets you a warning now: "Unchecked assignment: 'java.util.Map to java.util.Map<java.lang.Integer, java.lang.String>'.

Even though the signature of getMap is totally independent of T, and the code is unambiguous regarding the types the Map contains.

I know that I can get rid of the warning by reimplementing processA as follows:

public <T> void processA(A<T> a) {
    Map<Integer, String> map = a.getMap();
}

But why would I have to do that? What does T matter here at all?

So, the question is - why does type erasure have to not only affect T (which is understandable - if I'm passing an instance of A, T is an unknown), but also "hardcoded" generic signature like <Integer, String> in this case?


Solution

  • In your second case when you do:

    public void processA(A a)
    

    What do you mean by A? Does it mean A<String> or A<List<String>> or what? You might not be using anything related to type of A, but hey the compiler doesn't know this fact. To compiler, just A is a sign of panic.

    In your case, because you dont specifically need to know the type of A, you can:

    public void processA(A<?> a) {
        Map<Integer, String> map = a.getMap();
    } 
    

    Having an argument type of A<?> means, you do not specifically care the type of A and just specify a wild card. To you it means: any object of A with any type as its generic type would do. In reality, it means you do not know the type. Its useless because you cannot do anything related to A in typesafe manner as ? can be virtually anything!

    But as per your method body, it makes all the sense in the world to use A<?> because no where in the body you actually need the type of A