Generics - define Map<MyClassA<?>, MyClassB<?>> ensuring both ? are the same?

Matthew McPeak :

I have a line of code:

private final Map<MyClassA<?>, MyClassB<?>> myMap = new HashMap<>();

Is there any way to define that map in a way that would tell the compiler that the ? in each case must be the same class?

Something like this?

private final <T> Map<MyClassA<T>, MyClassB<T>> myMap = new HashMap<>();

... which is not legal syntax?

It's just a self-learning question at this point.

FWIW, I want to add a method

public <T> MyClassB<T> getForA(MyClassA<T> a) {
    return this.myMap.get(a);
}

But I get a compile error unless I can define myMap to insist that both the key and the value wrap the same type.

Johannes Kuhn :

As you already figured out, you can't do that if key and value are different for different entries:

map.put(new MyClassA<Foo>(), new MyClassB<Foo>());
map.put(new MyClassA<Bar>(), new MyClassB<Bar>());

(I've taken this requirement from your comment)

What you can do is to write some helper methods, which enforce this constraint:

public <T> void put(MyClassA<T> key, MyClass<B> value) {
    // Maybe check at runtime if the constraint is not validated?
    map.put(key, value);
}

public <T> MyClassB<T> get(MyClassA<T> key) {
    // This will produce an unchecked warning.
    return (T) map.get(key);
}

As long as you only access the map through such helper methods (and don't use raw types), the constraint on the map will not be violated, which allows you to write type safe code.

The only part that is not typesafe are those helper methods, and that's where you have to be careful.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325065&siteId=1