Java – Is it possible to combine two types to create another TypeLiteral?

Is it possible to combine two types to create another TypeLiteral?… here is a solution to the problem.

Is it possible to combine two types to create another TypeLiteral?

Given this method signature, is it possible to implement it? If yes, what to do?

TypeLiteral<MyClass<T, R>> combineTypes(Class<T> typeOne, Class<R> typeTwo) {
   Awesome implementation here
}

Background

I

have an interface, ApiHandler<TReq, TRes> I’m trying to use Guice to create in a factory, given type TReq. Unfortunately, TReq and TRes don’t have meaningful parent classes or interfaces for reasons beyond my control (they are generated from Apache Thrift).

Solution

If you evaluate it based on runtime parameters, it is no longer literal: it is just a type.

While you can use Guava’s equivalent TypeToken framework and its utilities, there is a Type utility class built into Guice: com.google.inject.util.types newParameterizedType(Type rawType, Type... typeArguments) to create the type you want, noting that both ParameterizedType and Class implement types.

static ParameterizedType combineTypes(Class<?> typeOne, Class<?> typeTwo) {
  return Types.newParameterizedType(MyClass.class, typeOne, typeTwo);
}

Unfortunately, AbstractModule.bin and LinkedBindingBuilder.to do not provide overloads for types; Only Class, TypeLiteral, and Key. Fortunately, you can use type reflection to generate keys, using Key.get (Type) :

bind(Key.get(combineTypes(Foo.class, Bar.class))).to(MyClassFooBar.class);

Note that the ParameterizedType itself is not a parameterized type here. This breaks some of Guice’s ingenious generic-based protection bind EDSL offers. For the above to work, you may need to @SuppressWarnings , return the primitive type Key, or consider having combineTypes return Key<MyClass<T, R>> (this needs to be done from Key.get(Type) The return value of Key<?> is converted). If you really have to use TypeLiteral, you can do it Key.getTypeLiteral Generate a TypeLiteral. , but this also requires type conversion from TypeLiteral<?>—and won’t be any meaningful definition of “type literal”.

Related Problems and Solutions