Java – Unchecked assignment warning
gets you a warning now: «Unchecked assignment: ‘java.util.Map to java.util.Map’ .
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 void processA(A a) < Mapmap = 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 in this case?
Best Solution
In your second case when you do:
What do you mean by A ? Does it mean A or A 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) < Mapmap = 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
Related Solutions
Java – What causes javac to issue the “uses unchecked or unsafe operations” warning
This comes up in Java 5 and later if you’re using collections without type specifiers (e.g., Arraylist() instead of ArrayList() ). It means that the compiler can’t check that you’re using the collection in a type-safe way, using generics.
To get rid of the warning, just be specific about what type of objects you’re storing in the collection. So, instead of
List myList = new ArrayList();
List myList = new ArrayList();
In Java 7 you can shorten generic instantiation by using Type Inference.
List myList = new ArrayList<>();
Java – Type safety: Unchecked cast
The problem is that a cast is a runtime check — but due to type erasure, at runtime there’s actually no difference between a HashMap and HashMap for any other Foo and Bar .
Use @SuppressWarnings(«unchecked») and hold your nose. Oh, and campaign for reified generics in Java 🙂
Related Question
Unchecked assignment warning
What do you mean by A ? Does it mean A or A 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) < Mapmap = 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
Solution 2
When you mean to accept an A of any possible type T , but don’t need the T , this is correctly expressed by using a wildcard and writing A . Doing so will get rid of the warning in your code:
public void processA(A a) < Mapmap = a.getMap(); >
Using the bare type A is not treated equivalently. As explained in the Java Language Specification, raw types like that are not intended to be used in new code:
Unchecked conversion is used to enable a smooth interoperation of legacy code, written before the introduction of generic types, with libraries that have undergone a conversion to use genericity (a process we call generification). In such circumstances (most notably, clients of the Collections Framework in java.util), legacy code uses raw types (e.g. Collection instead of Collection). Expressions of raw types are passed as arguments to library methods that use parameterized versions of those same types as the types of their corresponding formal parameters.
Such calls cannot be shown to be statically safe under the type system using generics. Rejecting such calls would invalidate large bodies of existing code, and prevent them from using newer versions of the libraries. This in turn, would discourage library vendors from taking advantage of genericity. To prevent such an unwelcome turn of events, a raw type may be converted to an arbitrary invocation of the generic type declaration to which the raw type refers. While the conversion is unsound, it is tolerated as a concession to practicality. An unchecked warning is issued in such cases.
Konrad Morawski
Software engineer with a few years of professional experience, skilled in C# and Java (I’ve done some work in PHP as well). Microsoft Certified Technology Specialist in Windows applications. Also active on: http://programmers.stackexchange.com/users/29029/konrad-morawski My profile on LinkedIn: http://pl.linkedin.com/pub/konrad-morawski/a6/129/b07 http://memegenerator.net/Computer-Programmer http://cdn.meme.am/instances/500x/63043797.jpg
Comments
public static class A < public MapgetMap() < return null; >> public static class B < public void processA(A a) < Mapmap = a.getMap(); > >
public static class A < public MapgetMap() < return null; >>
gets you a warning now: «Unchecked assignment: ‘java.util.Map to java.util.Map
public void processA(A a) < Mapmap = 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
You might not be using anything related to type of A, but hey the compiler doesn’t know this fact — well, it could get to know it quite easily, just take a look at the implementation of processA , it’s not hard to verify that T is irrelevant 😉 I’ll go with as you suggest, but I’m disappointed with the compiler.
@KonradMorawski In an ideal world, just A should be illegal and the code shouldn’t compile. But it is allowed for backward compatibility reasons. For a class declared as A
Yeah, I imagine. I don’t use Scala, but I come from the C# side of the world and Java’s generics feels like wearing shoes too small.
@KonradMorawski Moreover it is practically impossible for the compiler to know it. You might be doing reflection or doing a cast and working along. It is plainly extremely difficult to suggest with 100% conviction, that the type is not used.
@KonradMorawski Well agreed :). But in java world, backward compatibility >>>> anything else. So it is how it is 🙂
@Jatin — Thanks for this answer. This is first explanation of wildcards that has made clear sense to me. (Perhaps because I had run into the exact issue of the questioner, where I had a parameterized class with an explicitly parameterized method which warned of an unchecked assignment on usage.)