JohnRW JohnRW - 7 months ago 14
Java Question

Create Collection (e.g. Map) with specified Types - not using generic Object class

Is it possible to create a Map with specified types and not generic Object class objects?

Lets say i have a Type object that is

javafx.collections.ObservableMap<java.lang.Integer, java.lang.String>


and i get the subtypes of the map like this:

Class<?> keyClass = Class.forName(objectGenericTypes[0].getTypeName());
Class<?> valueClass = Class.forName(objectGenericTypes[1].getTypeName());


Can i create a Map object with the specified
Integer
and
String
classes from those
keyClass
and
valueClass
objects without using
Map<Object,Object>
? (
Integer
and
String
can be any other Class)

Answer

Type parameters in Java are not reified, due to type erasure. (There is an exception to this: if you create a concrete subclass of a generic type, then the type parameters for the parent class are "hard coded" into the subclass and can be found using reflection. This technique is called Gafter's Gadget.)

In the common case where you create a type like new HashMap<String, Integer> there is nothing in the type at runtime that indicates the type parameters. Instead the type parameters are inserted as casts at the point where you use the corresponding values.

If you want to create a new map with the same type parameters, you'll need to capture them in the generic signature:

public static <K, V> Map<K, V> newMapWithParametersOf(Map<K, V> map) {
  return new HashMap<>();
}

Underneath the hood, the object returned here actually still is a HashMap<Object, Object> (or more accurately, a raw HashMap without any type parameters at all). Since the generic types are only used by the compiler this is safe: the compiled bytecode will have the necessary casts inserted at the places where the type is used instead.