Jackie
Jackie

Reputation: 23497

Cannot cast from Map<String,Object> to Map<String,List<Map<String,String>>>

I am upgrading the following code:

return this.getMethod().execute(mp);

Where the execute method has signature:

public Map<String,Object> execute(Object mp)

I have code that expects the return of the method to be Map<String, List<Map<String, String>>>, but the compiler is choking on the conversion. So can I / how do I get this to cast properly? And is there any change between Java 5 and 6 that would make this now a compile time issue?

Upvotes: 2

Views: 3813

Answers (2)

Paul Bellora
Paul Bellora

Reputation: 55213

As long as you're sure that the returned map will only contain values of type List<Map<String, String>>, then you need to use a double cast:

Map<String, Object> map = this.getMethod().execute(mp);
@SuppressWarnings("unchecked") //thoroughly explain why it's okay here
Map<String, List<Map<String, String>>> mapWithNarrowedTypes =
        (Map<String, List<Map<String, String>>>)(Map<?, ?>)map;
return mapWithNarrowedTypes;

Upvotes: 7

Julian Cardona
Julian Cardona

Reputation: 11

Often for this type of problem I find useful the following construct:

public final class Reinterpret {

    @SuppressWarnings("unchecked")
    public static <T> T cast(Object object) {
        return (T)object;
    }

}

Which you can use, e.g., like this:

...
public void process(Map<String, Object> data) {
    // method can properly handle any Object value,
    // including String
}

...
    Map<String, String> stringData = ...
    process(Reinterpret.<Map<String, Object>>cast(stringData));
...

As you can guess, that very precise weakening of Java generics type system was inspired by C++'s reinterpret_cast operator, and is applicable in similar contexts; however, it can also be used in a few others, such as when you want to reduce the verbosity of your casts, e.g.,

    Map<String, Object> objectMap = Reinterpret.cast(stringMap);

Java 6's type inference is strong enough (or weak enough, depending on your perspective) to cast the right-hand-side expression to what the left-hand-side requires; notice, however, that this works fine for assignments, but NOT for function calls, which is why the example above requires fully specifying the parametric types in the call itself.

Upvotes: 1

Related Questions