How to check types of key and value if Object instanceof HashMap?

Shaun Scovil picture Shaun Scovil · Oct 3, 2013 · Viewed 60.5k times · Source

I have a method that accepts an Object. In one use case, the method accepts a HashMap<String, String> and sets each value to the property of the corresponding key name.

public void addHelper(Object object) {
    if (object instanceof HashMap) {
        HashMap<String, String> hashMap = (HashMap<String, String>) object;
        this.foo = hashMap.get("foo");
        this.bar = hashMap.get("bar");
    }
}

This class adheres to a particular interface, so adding setters for those properties is not an option.

My question is, how can I check the type cast here?

HashMap<String, String> hashMap = (HashMap<String, String>) object;

Thanks in advance!

SOLUTION

Thanks to the answer from @drobert, here is my updated code:

public void addHelper(Object object) {
    if (object instanceof Map) {
        Map map = (Map) object;
        if (map.containsKey("foo")) this.foo = map.get("foo").toString();
        if (map.containsKey("bar")) this.bar = map.get("bar").toString();
    }
}

Answer

drobert picture drobert · Oct 3, 2013

You can't. Due to type erasure, reflection will show you have an instance of HashMap, but the types are dropped at runtime. Effectively, you have HashMap< Object,Object >.

That said, you still have some options, and some advice I'd suggest you take. Among them:

  • Check to see if it's an instance of 'Map' rather than 'HashMap'. It will make your API much more flexible since you most likely only care that you have rapid access by key rather than any particular impementation
  • Take advantage of java.util.Map's api which defines 'containsKey(Object)' and 'get(Object)', so you can still use mapInst.get("stringKey") safely, even without having to cast.
  • You can't ensure all values are strings, but you can take advantage of java.lang.Object's toString() method and obtain a String for each value regardless.

In short: treat this like any Map, and attempt to access the keys as Strings even without the cast, and attempt to utilize each value as a String by doing a null check then calling .toString() and you'll have a much safer implementation.