2

I have a problem with Java Generics and I'm not sure if it's even possible what I want to get. Basically title says it all but let me give you an example. Currently I have something like this:

private static Map<Class<? extends Exception>, ExceptionTranslator<?>> MAP;

which is being used in a following way:

MAP.put(SomeException.class, new ExceptionTranslator<SomeException>());

But I would like to enforce a translator of the exception type passed as a key, something similar to what you do on methods:

<T extends Exception> Map<Class<T>, ExceptionTranslator<T>> MAP;

This of course is not a correct code and I guess my generics-foo is not strong enough for this. Is it even possible in Java?

3
  • 1
    Why your class doesn't has the <T extends Exception> generic in its definition? Commented Aug 9, 2013 at 22:27
  • 2
    You can't do this with just a normal Map; you have to do your own wrapping with a method that enforces the type constraint. Commented Aug 9, 2013 at 22:38
  • Thanks, @Louis. "You can't do it" is a valid response and I will accept your answer if you give me the chance. And well, I guess I will need to do what you guys did in Guava: code.google.com/p/guava-libraries/source/browse/guava/src/com/… Commented Aug 9, 2013 at 23:03

2 Answers 2

2

I just want to explain why it is impossible.

The problem is that it is impossible to guarantee type safety. The Map relies on equals/hashMap, which is impossible for compiler to prove correctness of these methods in relation with T type.

Imagine if instead of Class you would use your own generic class which will return equals==true for all its instances. In this case you could put into the map one type, but extract with another, it will produce cast exceptions:

private<E extends Number> void mp()
{
    Map<Key<E>, E> map = new HashMap<>();
    map.put(new Key<Integer>(), 42);// Yes, there is compilation error!
    // Otherwise we could do this:
    String str = map.get(new Key<String>());// cast exception!
}

class Key<T>
{
    @Override
    public int hashCode()
    {
        return 0;
    }

    @Override
    public boolean equals(final Object obj)
    {
        return obj instanceof Key;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

You can't do this with just a normal Map; you have to do your own wrapping with a method that enforces the type constraint. See the related question Java generics enforce same type for keys and values of map.

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.