You can't declare a map in this way. Basically, Java does not have an expressive-enough type system for this.
But luckily, the language provides an escape hatch from using the type system, in the form of casts. Basically, casts are a way to provide type information that the compiler doesn't have; the onus is then on you, however, to make sure that it actually is type safe.
Firstly, declare the map with wildcard types:
private final Map<A<?>,B<?>> map;
Then, only put key/value pairs into the map which do meet the constraint:
<T> void put (A<T> key, B<T> value) {
map.put(key, value);
}
And then cast when you get the element out again:
@SuppressWarnings("unchecked") // Safe
<T> B<T> get(A<T> key) {
return (B<T>) map.get(key);
}
The point is that you can know more about the types than the compiler. Provided you take care to only put in safely-castable pairs, it is safe to cast them. (You also need to ensure that the equals method takes the type into account, so no A<T> equals A<S> unless S == T).
This is basically a "type-safe heterogeneous container", as described in Effective Java (Item 33 in 3rd Edition).
I am wondering if there is a more elegant way that does not require me to cast every value I retreive.
For one thing, you aren't actually doing a cast in the get method at runtime: that's what an unchecked cast means.
For another, generics introduces loads of casts - basically generics is just a way to avoid inserting casts manually. So if there were a problem with the casts (such as performance), you'd already observe this in lots of places.
To paraphrase Kubrick: stop worrying, and love the cast.
Mapthat way. Possibly see stackoverflow.com/questions/44422685/… for some examples of workarounds (possible duplicate?).getmethod gets something, as opposed to wiping your hard drive, right? In the same way, you have to trust (or prove otherwise) that the code is type safe.