Eclipse is giving me a warning of the following form:
Type safety: Unchecked cast from Object to HashMap
This is from a call to an API that I have no control over which returns Object:
HashMap<String, String> getItems(javax.servlet.http.HttpSession session) { HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey"); return theHash; }
I'd like to avoid Eclipse warnings, if possible, since theoretically they indicate at least a potential code problem. I haven't found a good way to eliminate this one yet, though. I can extract the single line involved out to a method by itself and add @SuppressWarnings("unchecked")
to that method, thus limiting the impact of having a block of code where I ignore warnings. Any better options? I don't want to turn these warnings off in Eclipse.
Before I came to the code, it was simpler, but still provoked warnings:
HashMap getItems(javax.servlet.http.HttpSession session) { HashMap theHash = (HashMap)session.getAttribute("attributeKey"); return theHash; }
Problem was elsewhere when you tried to use the hash you'd get warnings:
HashMap items = getItems(session); items.put("this", "that"); Type safety: The method put(Object, Object) belongs to the raw type HashMap. References to generic type HashMap<K,V> should be parameterized.
If we can't eliminate the “unchecked cast” warning and we're sure that the code provoking the warning is typesafe, we can suppress the warning using the SuppressWarnings(“unchecked”) annotation. When we use the @SuppressWarning(“unchecked”) annotation, we should always put it on the smallest scope possible.
Unchecked cast means that you are (implicitly or explicitly) casting from a generic type to a nonqualified type or the other way around.
@SuppressWarnings("unchecked") is used when Java generics just don't let you do what you want to, and thus, you need to explicitly specify to the compiler that whatever you are doing is legal and can be executed at the time of execution.
The obvious answer, of course, is not to do the unchecked cast.
If it's absolutely necessary, then at least try to limit the scope of the @SuppressWarnings
annotation. According to its Javadocs, it can go on local variables; this way, it doesn't even affect the entire method.
Example:
@SuppressWarnings("unchecked") Map<String, String> myMap = (Map<String, String>) deserializeMap();
There is no way to determine whether the Map
really should have the generic parameters <String, String>
. You must know beforehand what the parameters should be (or you'll find out when you get a ClassCastException
). This is why the code generates a warning, because the compiler can't possibly know whether is safe.
Unfortunately, there are no great options here. Remember, the goal of all of this is to preserve type safety. "Java Generics" offers a solution for dealing with non-genericized legacy libraries, and there is one in particular called the "empty loop technique" in section 8.2. Basically, make the unsafe cast, and suppress the warning. Then loop through the map like this:
@SuppressWarnings("unchecked") Map<String, Number> map = getMap(); for (String s : map.keySet()); for (Number n : map.values());
If an unexpected type is encountered, you will get a runtime ClassCastException
, but at least it will happen close to the source of the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With