Skip to content

Reflection Framework

Mike Strobel edited this page Oct 27, 2019 · 1 revision

Types

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>.

Types from Classes

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

Primitives and Other Built-In Types

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.

Array Types

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.

Parameterized Types (Generic Instance Types)

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.

Wildcard Types

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

Compound Types

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

Type Members

Coming soon (this wiki is a work in progress).