Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve this Java type safety warning?

Map session = ActionContext.getContext().getSession();
session.put("user", user);

This code generates a warning: Type safety: The method put(Object, Object) belongs to the raw type Map. References to generic type Map<K,V> should be parameterized.

Map<String, Serializable> session = (Map<String, Serializable>)ActionContext.getContext().getSession();
session.put("user", user);

This code generates a warning: Type safety: Unchecked cast from Map to Map<String,Serializable>.

The getSession method belongs to Struts2 so I can't modify it. I would like to avoid using @SuppressWarnings because other warnings can be useful.

I guess all Struts2 users in the world faced the same problem... is there an elegant solution?

like image 246
Nicolas Raoul Avatar asked May 28 '10 07:05

Nicolas Raoul


2 Answers

The safest, most efficient way to deal with this is probably:

Map<?, ?> session = ActionContext.getContext().getSession();

and then type cast the objects retrieved from the session map.

The @SuppressWarnings approach will actually result in compiled code that is identical. However the type cast will be implicit; i.e. it won't be easy to spot by looking at the source code. And the @SuppressWarnings annotation could (hypothetically) suppress some other warning in the same code block that represents a real error; i.e. one that will result in one of the hidden typecasts, etc failing at runtime.

Other more expensive alternatives include:

  • an entry by entry copy from the Map<?, ?> to a new Map<String, Serializable> instance casting the keys and values to String and Serializable respectively, or

  • a generic method like the following that performs the typecast safely.


@SuppressWarnings("unchecked")
public <K,V> Map<K,V> castMap(Map<?, ?> map, Class<K> kClass, Class<V> vClass) {
    for (Map.Entry<?, ?> entry : map.entrySet()) {
        kClass.cast(entry.getKey());
        vClass.cast(entry.getValue());
    }
    return (Map<K,V>) map;
}
like image 56
Stephen C Avatar answered Oct 05 '22 02:10

Stephen C


I don't think there's any other way but @SuppressWarnings("unchecked"). I believe you can put it just above the line in question, and it will only suppress that line.

Edit: you can also do Map<?, ?> session = ActionContext.getContext().getSession(); but I'm not sure how willing you are to do that; you won't be able to put anything into the map that way (since the compiler can't check the type of what you're putting), only read from it.

like image 36
Andrei Fierbinteanu Avatar answered Oct 05 '22 02:10

Andrei Fierbinteanu