TypeLiteral implements Serializable { protected Type getDefinedType(Class<?> clazz) { Type type; if (clazz == null) { throw new RuntimeException("Class parameter clazz can not be null"); } Type superClazz = clazz.getGenericSuperclass(); if (superClazz instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) superClazz; Type[] actualArgs = pt.getActualTypeArguments(); if (actualArgs.length == 1) { type = actualArgs[0]; } else { throw new RuntimeException("More than one parametric type"); } } else if (superClazz.equals(Object.class)) { throw new RuntimeException("Super class must be parametrized type"); } else { type = getDefinedType((Class<?>) superClazz); } return type; } TypeLiteral(Type definedType);  TypeLiteral(); static TypeLiteral<R> of(Type type); static Type[] getGenericInterfaceTypeParameters(Class<?> clazz, Class<?> interfaceType); static Type[] getTypeParameters(Type type); final Type getType(); @SuppressWarnings("unchecked") final Class<T> getRawType(); @Override int hashCode(); @Override boolean equals(Object obj); @Override String toString();  }
@Test public void testTypeTakingParametersMustBeSubclassOfParameterizedType() { class A extends ArrayList<String> { }; class B extends A { }; TypeLiteral<List<String>> checker = new TypeLiteral<List<String>>() { }; Type t = checker.getDefinedType(B.class); assertThat("java.lang.String").isEqualTo(t.getTypeName()); }
@SuppressWarnings("rawtypes") @Test(expected = RuntimeException.class) public void testTypeTakingParametersMustNotBeSubclassOfObject() { class A<T> { }; class B extends A { }; TypeLiteral<List<String>> checker = new TypeLiteral<List<String>>() { }; checker.getDefinedType(B.class); }