T
- The type represented by this type literal.public abstract class TypeLiteral<T> extends Object
T
, where T
may be a generic type that need not be reifiable.
The type of T
can be retrieved with the TypeLiteral.getType()
method. It can
represent a class, a type variable, a wild-card type, a component type of a generic
type array, or a type parameter of a parameterised type with a single type parameter
(also called a component type).
The raw type of T
can be retrieved with the TypeLiteral.getRawType()
method
if T
does not represent a type variable, a wild-card, or a generic array
type storing type variables.
A type literal can also represent non-reifiable types. Hence, there can be
inconsistencies between T
and the actual type represented by the literal
because of erasure: though T
may seem to represent a known type in the
literal, say Integer
as in TypeLiteral<Integer>
, the actual type can represent a type variable, say S
, as
is illustrated in the examples below (see for example literal5
). This is normally not an issue if type literals are created explicitly and
not by generic methods or through extended inheritance.
Examples:
// Standard creation...
// T = Integer, type = class, raw type = Integer class
TypeLiteral<Integer> literal1 = new TypeLiteral<Integer>(){};
// T = Object[], type = generic array type, raw type = Object class
TypeLiteral<Object[]> literal2 = new TypeLiteral<Object[]>(){};
// T = Class<String>[], type = generic array type, raw type = Class class
TypeLiteral<Class<String>[]> literal3 = new TypeLiteral<Class<String>[]>(){};
// T = List<?>, type = class, raw type = List interface
TypeLiteral<List<?>> literal4 = new TypeLiteral<List<?>>(){};
// Factory creation...
// Generic factory methods...
public static <S> TypeLiteral<S> create1(S value) {
return new TypeLiteral<S>(){};
}
public static <R> TypeLiteral<Comparable<R>> create2(R value) {
return new TypeLiteral<Comparable<R>(){};
}
// Potential trouble: T = Integer, type = type variable (S), raw type = null
TypeLiteral<Integer> literal5 = create1(new Integer(1));
// Potential trouble: T = Class<Integer>, type = type variable (S), raw type = null
TypeLiteral<Class<Integer>> literal6 = create1(Integer.class);
// Potential trouble: T = Class<Integer>, type = type variable (S), raw type = null
TypeLiteral<Class<Integer>> literal7 = create1(null);
// Potential trouble: T = Comparable<Long>,
// type = parameterised type (with type parameter R), raw type = Comparable interface
TypeLiteral<Comparable<Long>> literal8 = create2(Long.class);
// Potential trouble: T = Comparable<Object>,
// type = parameterised type (with type parameter R), raw type = Comparable interface
TypeLiteral<Comparable<Object>> literal9 = create2(null);
// Inheritance...
class Foo extends TypeLiteral<ArrayList<?>>{};
class FooFoo extends TypeLiteral<CharSequence>{};
class Bar extends Foo {};
class Goo<K,V> extends TypeLiteral<Map<K,V>>{};
class FooGoo<K,V> extends TypeLiteral<Map<Long,Void>>{};
class FooBar extends Goo<String,Void> {};
// T = ArrayList<?>, type = parameterised type, raw type = ArrayList class
Foo literal10 = new Foo();
// T = CharSequence, type = class, raw type = CharSequence interface
FooFoo literal11 = new FooFoo();
// Potential trouble: T = Map<K,V>, type = parameterised type, raw type = Map interface
Goo literal12 = new Goo<String,Integer>();
// T = Map<Long,Void>, type = parameterised type, raw type = Map interface
FooGoo literal13 = new FooGoo<String,Integer>();
// Throws illegal argument exception: Bar has no immediate generic super type
Bar literal14 = new Bar();
// Potential trouble: FooBar's immediate generic super type has two type parameters:
// <String,Void>, and so the first, e.g. String
, is used.
FooBar literal15 = new FooBar();
Implementation notes:See [Langer06], for example technical details FAQ106, for an easily understandable discussion on reifiable types and erasure. It contains condensed information from The Java Language Specification, Third Edition [ Gosling05] about reifiable types.
Modifier and Type | Field and Description |
---|---|
protected Type |
type
The actual
Type object representing the type realised as the type parameter
T . |
Modifier | Constructor and Description |
---|---|
protected |
TypeLiteral()
Constructor, which creates this type literal to represent the type represented by
the type parameter
T . |
|
TypeLiteral(TypeLiteral<T> typeLiteral)
Copy constructor, which creates this type literal based on the type represented by
typeLiteral . |
Modifier and Type | Method and Description |
---|---|
Class<T> |
asClass()
|
Class<T> |
asClass(Class<?> clazz)
Returns a view of the class represented by
clazz as the
type represented by this type literal, if possible. |
<S> TypeLiteral<T> |
asType(TypeLiteral<S> typeLiteral)
Returns a view of
typeLiteral as the type represented by this type
literal, T instead of S , if possible. |
static <S> TypeLiteral<?> |
create(Class<S> clazz)
Returns a type literal representing the generic super-type of class supplied as
clazz . |
static TypeLiteral<?> |
create(Object object)
Returns a type literal representing the generic super-type of class of
object . |
static TypeLiteral<?> |
create(Type type)
Returns a type literal representing the component type supplied via
type . |
boolean |
equals(Object object)
Returns true of
object is a type literal representing the same
type as this type literal, false if not. |
static Type |
getComponentType(Type type)
Returns the component type of the type supplied as
type if a
parameterised type or generic array type, otherwise type itself. |
Class<?> |
getRawType()
Returns the raw type represented by this type literal, if any.
|
static Class<?> |
getRawType(Type type)
Returns the raw type represented by the type supplied as
type , if any. |
Type |
getType()
Returns the type represented by this type literal.
|
int |
hashCode()
Return the hash code of this type literal.
|
String |
toString()
Returns the string representation of this type literal.
|
protected final Type type
Type
object representing the type realised as the type parameter
T
.
Never null.
protected TypeLiteral()
T
.IllegalArgumentException
- If this class is not generic.public TypeLiteral(TypeLiteral<T> typeLiteral)
typeLiteral
.typeLiteral
- The type literal to copy; cannot be null.NullPointerException
- If typeLiteral
is null.public static <S> TypeLiteral<?> create(Class<S> clazz)
clazz
.
S
- The type of clazz
.clazz
- The class literal representing the type; cannot be null.NullPointerException
- If clazz
is null.TypeLiteral.create(Type)
public static TypeLiteral<?> create(Object object)
object
.object
- The object to supply the class; cannot be null.object
; never null.NullPointerException
- If object
is null.public static TypeLiteral<?> create(Type type)
type
.type
- The type; cannot be null.type
; never null.NullPointerException
- If type
is null.TypeLiteral.getComponentType(Type)
,
TypeLiteral.create(Class)
public Class<T> asClass()
type
represented by this type
literal as a class literal if and only if the type has a raw
type
.
Note, that if the type is generic, the returned class literal actually represents the raw type!
TypeLiteral.asClass(Class)
,
TypeLiteral.asType(TypeLiteral)
public Class<T> asClass(Class<?> clazz)
clazz
as the
type
represented by this type literal, if possible.
This type must have a raw type
for this method to have a
chance of succeeding.
Note, that if the type is generic, the returned class literal actually represents the raw type!
clazz
- The class to view as the type represented by this type literal; cannot
be null.NullPointerException
- If clazz
is null.ClassCastException
- If clazz
cannot be viewed as the type represented by this type
literal.TypeLiteral.asClass()
,
TypeLiteral.asType(TypeLiteral)
public <S> TypeLiteral<T> asType(TypeLiteral<S> typeLiteral)
typeLiteral
as the type represented by this type
literal, T
instead of S
, if possible.
If a cast from S
to T
is not possible, a class cast exception is
thrown. If the type
represented by this type literal does not
have a raw type
, a class cast exception will also be thrown.
Two will card types will cause a class cast exception, as a simple cast will
suffice.
The test for matching types is done recursively, including test for generic array and parameter types with bounded and/or unbounded wild-cards.
S
- The type represented by typeLiteral
.typeLiteral
- The type literal; cannot be null.typeLiteral
casted to represent T
instead of S
, if
possible; never null.NullPointerException
- If typeLiteral
is null.IllegalArgumentException
- If either T
or S
recursively do not represent a
parameterised type.ClassCastException
- If typeLiteral
cannot represent T
.TypeLiteral.getComponentType(Type)
,
TypeLiteral.asClass()
,
TypeLiteral.asClass(Class)
public Type getType()
TypeLiteral.getComponentType(Type)
public static Type getComponentType(Type type)
type
if a
parameterised type or generic array type, otherwise type
itself.
If there are more than one parameter types, the first one is used, and the additional ones ignored.
The component type may be a generic type.
type
- The type to supply the component type, if any; cannot be null.NullPointerException
- If type
is null.IllegalArgumentException
- If type
is a parameterised type with no type parameters (if
more than one, the first one is used). Zero type parameters can occur
if type
type represents a non-parameterised type nested within
a parameterised type.public Class<?> getRawType()
A raw type cannot be returned if this type literal represents a type variable, a wild-card, or a generic array type storing type variables.
The raw type may be the same as TypeLiteral.getType()
.
TypeLiteral.getRawType(Type)
public static Class<?> getRawType(Type type)
type
, if any.
A raw type cannot be returned if type
is a type variable, a wild card, or a
generic array type storing type variables.
type
- The type to use; cannot be null.NullPointerException
- If type
is null.public int hashCode()
hashCode
in class Object
Object.equals(java.lang.Object)
,
System.identityHashCode(java.lang.Object)
public boolean equals(Object object)
object
is a type literal representing the same
type
as this type literal, false if not.equals
in class Object
object
- The object to test; can be null.Object.hashCode()
,
HashMap