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);