14
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?

sjngm
  • 12,423
  • 14
  • 84
  • 114
Nicolas Raoul
  • 58,567
  • 58
  • 222
  • 373

8 Answers8

11

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.

Andrei Fierbinteanu
  • 7,656
  • 3
  • 31
  • 45
7

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;
}
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

It is requesting you to parameterize the value, if the value needs parameters then pass them.

For example

Map<Integer, Map> vCombinedCodeMap = new HashMap<>();

will give warning for "parameterized" Map<Integer, Map>.

so the correct format is the following:

Map<Integer, Map<String, String>> vCombinedCodeMap = new HashMap<>();
Sk8erPeter
  • 6,899
  • 9
  • 48
  • 67
1

What version of Struts 2 (especially XWork) are you using? For me, your following code gives an error:

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

Cannot cast from Map<String,Object> to Map<String,Serializable>.

This, on the other hand, works and gives no warnings:

Map<String, Object> session = ActionContext.getContext().getSession();
Tommi
  • 8,550
  • 5
  • 32
  • 51
  • I use 2.1.8.1 which is the latest version. Your suggestion gives this warning: Type safety: The expression of type Map needs unchecked conversion to conform to Map – Nicolas Raoul May 28 '10 at 08:17
  • 1
    http://struts.apache.org/2.1.8.1/struts2-core/apidocs/com/opensymphony/xwork2/ActionContext.html It seems that the 2.1.8.1 getSession should return a parameterized map. Are you sure it's properly installed and not using an older version previously installed? – Andrei Fierbinteanu May 28 '10 at 08:23
  • 1
    @Nicolas Raoul: Something is different in our environments then since I don't get a warning. I would still check what XWork version you're using. – Tommi May 28 '10 at 08:29
  • Indeed I actually had two versions installed and was mistakenly using an older one, sorry for the confusion, and thanks a lot for your help! – Nicolas Raoul May 28 '10 at 08:35
0

Cast as Following,

public void setSession(Map<String, Object> sessionMap) {

    // TODO Auto-generated method stub

    this.sessionMap = (SessionMap<String, Object>) sessionMap;
}
0

What if you do it like this:

Map<String, Serializable> session = ActionContext.getContext().getSession();
Adrian Toman
  • 11,316
  • 5
  • 48
  • 62
zed_0xff
  • 32,417
  • 7
  • 53
  • 72
0

just write @SuppressWarnings("unchecked") at top of the @GET method, hope it will help you.

YosiFZ
  • 7,792
  • 21
  • 114
  • 221
0
@SuppressWarnings("unchecked")
public class CustomHashMap<K, V> {

  private class Entry {
    private K key;
    private V value;

    public Entry(K key, V value) {
      this.key = key;
      this.value = value;
    }

  }

  private LinkedList<Entry>[] entries = new LinkedList[5]; // this line shows warning to check types
}
necimye
  • 59
  • 1
  • 3