Type Keys#
Many places in the Terra API make use of generics and Java’s Class class for type-safe reflective type handling. This approach generally works quite well.
The Issue#
What if you want a registry that registers instances of SomeObject<SomeOtherThing>
? Due to type erasure, this is
not immediately possible. You cannot access SomeObject<SomeOtherThing>.class
, as it simply does not exist at
runtime.
A naive solution is to simply use SomeObject.class
. This is not ideal for two reasons:
It breaks type safety.
SomeObject
now has no generic type.It will overwrite or be overwritten by anything else that attempts to register any generic type of
SomeObject
.
The Solution#
Terra includes an abstract class called TypeKey to solve this problem. All APIs which accept a Class
instance also accept a TypeKey
.
Getting a TypeKey#
To acquire a TypeKey
instance for your type, simply create an anonymous inner class
which extends TypeKey
with a generic type matching yours. In our SomeObject<SomeOtherThing>
example, that would
look like:
public static final TypeKey<SomeObject<SomeOtherThing>> SOME_OBJECT_SOME_OTHER_THING_KEY = new TypeKey<>() { };
Note
Notice that the TypeKey
is static final
. This is to reduce boilerplate by moving the key declaration to
the top of the class, and to reduce unneeded instantiation.
Getting a TypeKey from a Class instance#
To further reduce boilerplate, you can get a TypeKey directly from a Class instance by using the TypeKey#of(Class) method. This is useful if you need a TypeKey for a non-generic type.
TypeKey<Something> = TypeKey.of(Something.class);