-
Notifications
You must be signed in to change notification settings - Fork 118
Reflection Framework
The procyon-reflection
framework provides a rich type model inspired by the .NET Framework's System.Reflection
API. All types, including generic type variables and wildcards, are represented by the same Type<T>
.
The most straightforward way to obtain a Type<T>
instance is by calling Type.of(clazz)
where clazz
is a Class<T>
instance. If the specified class contains generic parameters, then the returned type is the generic type definition (e.g., List<E>
will be returned if List.class
is specified). The class argument may be a primitive, reference, or array type, and calling Type.of(String[].class)
is equivalent to calling Type.of(String.class).makeArrayType()
(see Array Types below).
For reduced overhead, type definitions for primitives and common JDK types are exposed via the PrimitiveTypes
and Types
classes. Any generic type exposed by Types
is always a generic type definition, i.e., all type variables are present and unbound.
There are two ways to obtain an array type definition. The preferred way to resolve Type<T[]>
for an element type T
is by calling elementType.makeArrayType()
where elementType
is a Type<T>
. Alternatively, array types can be obtained directly via Type.of(T[].class)
. These solutions are equivalent, though makeArrayType()
may perform slightly better.
Given a generic type definition Type<T>
, a generic instance type may be obtained via the type.MakeGenericType(Type<?>...)
method or one of its overloads. The arguments at the call site represent the types to which the target's type variables should be bound. The number of type arguments must exactly match the number of type variables.
For example, given the type Map<K, V>
, the type Type<Map<String, Integer>>
could be obtained as follows:
:::java
final Type<Map<String, Integer>> t = Types.Map.makeGenericType(Types.String, Types.Integer);
In the signatures of all members of type t
above, the types String
and Integer
would be substituted for K
and V
in, respectively.
The Type
class exposes three factory methods for obtaining wildcard types:
-
makeWildcard()
returns an unbounded wildcard (?
) -
makeExtendsWildcard(Type<T>)
returns a wildcard with an upper bound (? extends T
); -
makeSuperWildcard(Type<T>)
returns a wildcard with an lower bound (? super T
);
To create a compound type (e.g., the intersection of a base class and one or more interfaces), use one of the Type.makeCompoundType()
methods. You may want to do this to define a complex generic parameter bound.
:::java
// Obtain type 'A & B & C'
final Type<?> type = Type.makeCompoundType(
Type.of(A.class), // super class
Type.list(Type.of(B.class), Type.of(C.class)) // super interfaces
);
Coming soon (this wiki is a work in progress).