Skeletal implementation of interface javax.lang.model.util.Types
, plus concrete realization backed by core Java Reflection API, akin to JDK Enhancement Proposal (JEP) 119
Status
Overview
- source compatible with Java 7 and 8
- algorithms, relations, and properties of Java Language Specification implemented exclusively in terms of
javax.lang.model
interfaces; therefore supports different concrete implementations ofjavax.lang.model
interfaces - besides the generic skeletal implementation of
javax.lang.model.util.Types
, also includes a concrete implementation backed by the Java Reflection API - implemented in plain Java with no dependencies; easily embeddable in projects that have Java types as part of their domain model (for instance, domain-specific languages on top of the JVM that need some sort of support for Java generic types)
- contract tests for the methods and classes that clients of the library need to provide in order to support other implementations of
javax.lang.model
interfaces - tests have virtually full code coverage
- contains a complete implementation of
javax.lang.model.util.Types
methods pertaining to JLS §4 (including primitive types, reference types, type variables, parameterized types, type erasure, raw types, intersection types, and subtyping) and §5.1.10 (capture conversion) - also includes method for resolving formal type parameters to actual type arguments (for example, determining the actual type argument to
Comparable<T>
, given typeInteger
) - methods pertaining to non-type elements (notably,
ExecutableElement
andVariableElement
) not currently implemented - Code makes use of JSR 305 annotations (e.g.,
@Nullable
)
License
Revised BSD (3-Clause) License
Binary Releases
Published releases (compiled for Java 7 and up) are available on Maven Central.
<dependency>
<groupId>net.florianschoppmann.java</groupId>
<artifactId>java-types</artifactId>
<version>1.0.1</version>
</dependency>
Documentation
Usage Examples
The following examples show some use cases of class ReflectionTypes
, the Java Reflection API-based implementation of javax.lang.model.util.Types
provided by this project. While the bulk of the functionality of ReflectionTypes
is provided by an abstract, skeletal-implementation class called AbstractTypes
, class ReflectionTypes
provides methods typeElement()
and typeMirror()
that facilitate converting Java classes and generic types to TypeElement
and TypeMirror
instances.
Test whether one type is a subtype of another
(see JLS §4.10 and its references)
ReflectionTypes types = ReflectionTypes.getInstance();
// listSuperNumberType: List<? super Number>
DeclaredType listSuperNumberType = types.getDeclaredType(
types.typeElement(List.class),
types.getWildcardType(null, types.typeMirror(Number.class))
);
// iterableExtendsNumberType: Iterable<? extends Number>
DeclaredType iterableExtendsNumberType = types.getDeclaredType(
types.typeElement(Iterable.class),
types.getWildcardType(types.typeMirror(Number.class), null)
);
// iterableType: Iterable<?>
DeclaredType iterableType = types.getDeclaredType(
types.typeElement(Iterable.class),
types.getWildcardType(null, null)
);
assert types.isSubtype(listSuperNumberType, iterableType);
assert types.isSubtype(iterableExtendsNumberType, iterableType);
assert !types.isSubtype(listSuperNumberType, iterableExtendsNumberType);
Resolve actual type arguments
(see JLS §4.5, §8.1, and their references)
ReflectionTypes types = ReflectionTypes.getInstance();
// actual type arguments to Comparable, given the (raw) subtype ScheduledFuture
List<? extends TypeMirror> typeArguments = types.resolveActualTypeArguments(
types.typeElement(Comparable.class),
types.typeMirror(ScheduledFuture.class)
);
assert typeArguments.equals(
Collections.singletonList(types.typeMirror(Delayed.class))
);
Capture conversion with mutually recursive type-variable bounds
(taken from Example 8.1.2-1 of JLS 8, see also JLS §5.1.10 and its references)
// The following are top-level definitions
interface ConvertibleTo<T> {
T convert();
}
class ReprChange<T extends ConvertibleTo<S>,
S extends ConvertibleTo<T>> {
T t;
void set(S s) { t = s.convert(); }
S get() { return t.convert(); }
}
class Amount implements ConvertibleTo<Integer> {
@Override public Integer convert() { return 42; }
}
// [...]
ReflectionTypes types = ReflectionTypes.getInstance();
// reprChangeType: ReprChange<Amount, ?>
DeclaredType reprChangeType = types.getDeclaredType(
types.typeElement(ReprChange.class),
types.typeMirror(Amount.class),
types.getWildcardType(null, null)
);
TypeMirror convertedType = types.capture(reprChangeType);
TypeVariable capturedS
= (TypeVariable) ((DeclaredType) convertedType).getTypeArguments().get(1);
// convertibleToAmountType: ConvertibleTo<Amount>
DeclaredType convertibleToAmountType = types.getDeclaredType(
types.typeElement(ConvertibleTo.class),
types.typeMirror(Amount.class)
);
assert capturedS.getUpperBound().equals(convertibleToAmountType);