2

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?

4
  • 4
    Can you clarify what you mean by "between 5 and 6"? Commented Nov 14, 2012 at 15:59
  • 2
    i think he meant java version Commented Nov 14, 2012 at 15:59
  • 3
    Can you guarantee the map's values will only be List<Map<String, String>>? Why did someone use generics, but then put Object as the value type? Commented Nov 14, 2012 at 16:04
  • I can guarantee (this code works in prod today) but I can't really change the interface because that is someone else's code and would take time. Commented Nov 14, 2012 at 16:27

2 Answers 2

7

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;
Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.