Java 泛型之 JDK 的底层实现原理
Posted 东海陈光剑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 泛型之 JDK 的底层实现原理相关的知识,希望对你有一定的参考价值。
AnnotatedType
数组类型、参数化类型和 类型变量,或通配符类型.
package java.lang.reflect;
/**
* {@code AnnotatedType} represents the potentially annotated use of a type in
* the program currently running in this VM. The use may be of any type in the
* Java programming language, including an array type, a parameterized type, a
* type variable, or a wildcard type.
*
* @since 1.8
*/
public interface AnnotatedType extends AnnotatedElement {
/**
* Returns the underlying type that this annotated type represents.
*
* @return the type this annotated type represents
*/
public Type getType();
}
Tree 接口
package sun.reflect.generics.tree;
/** Root of the abstract syntax tree hierarchy for generic signatures */
public interface Tree{}
TypeTree
package sun.reflect.generics.tree;
import sun.reflect.generics.visitor.TypeTreeVisitor;
/** Common supertype for all nodes that represent type expressions in
* the generic signature AST.
*/
public interface TypeTree extends Tree {
/**
* Accept method for the visitor pattern.
* @param v - a <tt>TypeTreeVisitor</tt> that will process this
* tree
*/
void accept(TypeTreeVisitor<?> v);
}
类型 Type
package java.lang.reflect;
/**
* Type is the common superinterface for all types in the Java
* programming language. These include raw types, parameterized types,
* array types, type variables and primitive types.
*
* @since 1.5
*/
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
访问者模式 TypeTreeVisitor
Visit a TypeTree and produce a result of type T
package sun.reflect.generics.visitor;
import sun.reflect.generics.tree.*;
/**
* Visit a TypeTree and produce a result of type T.
*/
public interface TypeTreeVisitor<T> {
/**
* Returns the result of the visit.
* @return the result of the visit
*/
T getResult();
// Visitor methods, per node type
void visitFormalTypeParameter(FormalTypeParameter ftp);
void visitClassTypeSignature(ClassTypeSignature ct);
void visitArrayTypeSignature(ArrayTypeSignature a);
void visitTypeVariableSignature(TypeVariableSignature tv);
void visitWildcard(Wildcard w);
void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct);
void visitBottomSignature(BottomSignature b);
// Primitives and Void
void visitByteSignature(ByteSignature b);
void visitBooleanSignature(BooleanSignature b);
void visitShortSignature(ShortSignature s);
void visitCharSignature(CharSignature c);
void visitIntSignature(IntSignature i);
void visitLongSignature(LongSignature l);
void visitFloatSignature(FloatSignature f);
void visitDoubleSignature(DoubleSignature d);
void visitVoidDescriptor(VoidDescriptor v);
}
两个子类 Visitor , Reifier
Visitor
package sun.reflect.generics.visitor;
import sun.reflect.generics.tree.*;
public interface Visitor<T> extends TypeTreeVisitor<T> {
void visitClassSignature(ClassSignature cs);
void visitMethodTypeSignature(MethodTypeSignature ms);
}
Reifier
Visitor that converts AST to reified types.
package sun.reflect.generics.visitor;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Iterator;
import sun.reflect.generics.tree.*;
import sun.reflect.generics.factory.*;
/**
* Visitor that converts AST to reified types.
*/
public class Reifier implements TypeTreeVisitor<Type> {
private Type resultType;
private GenericsFactory factory;
private Reifier(GenericsFactory f){
factory = f;
}
private GenericsFactory getFactory(){ return factory;}
/**
* Factory method. The resulting visitor will convert an AST
* representing generic signatures into corresponding reflective
* objects, using the provided factory, <tt>f</tt>.
* @param f - a factory that can be used to manufacture reflective
* objects returned by this visitor
* @return A visitor that can be used to reify ASTs representing
* generic type information into reflective objects
*/
public static Reifier make(GenericsFactory f){
return new Reifier(f);
}
// Helper method. Visits an array of TypeArgument and produces
// reified Type array.
private Type[] reifyTypeArguments(TypeArgument[] tas) {
Type[] ts = new Type[tas.length];
for (int i = 0; i < tas.length; i++) {
tas[i].accept(this);
ts[i] = resultType;
}
return ts;
}
/**
* Accessor for the result of the last visit by this visitor,
* @return The type computed by this visitor based on its last
* visit
*/
public Type getResult() { assert resultType != null;return resultType;}
public void visitFormalTypeParameter(FormalTypeParameter ftp){
resultType = getFactory().makeTypeVariable(ftp.getName(),
ftp.getBounds());
}
public void visitClassTypeSignature(ClassTypeSignature ct){
// This method examines the pathname stored in ct, which has the form
// n1.n2...nk<targs>....
// where n1 ... nk-1 might not exist OR
// nk might not exist (but not both). It may be that k equals 1.
// The idea is that nk is the simple class type name that has
// any type parameters associated with it.
// We process this path in two phases.
// First, we scan until we reach nk (if it exists).
// If nk does not exist, this identifies a raw class n1 ... nk-1
// which we can return.
// if nk does exist, we begin the 2nd phase.
// Here nk defines a parameterized type. Every further step nj (j > k)
// down the path must also be represented as a parameterized type,
// whose owner is the representation of the previous step in the path,
// n{j-1}.
// extract iterator on list of simple class type sigs
List<SimpleClassTypeSignature> scts = ct.getPath();
assert(!scts.isEmpty());
Iterator<SimpleClassTypeSignature> iter = scts.iterator();
SimpleClassTypeSignature sc = iter.next();
StringBuilder n = new StringBuilder(sc.getName());
boolean dollar = sc.getDollar();
// phase 1: iterate over simple class types until
// we are either done or we hit one with non-empty type parameters
while (iter.hasNext() && sc.getTypeArguments().length == 0) {
sc = iter.next();
dollar = sc.getDollar();
n.append(dollar?"$":".").append(sc.getName());
}
// Now, either sc is the last element of the list, or
// it has type arguments (or both)
assert(!(iter.hasNext()) || (sc.getTypeArguments().length > 0));
// Create the raw type
Type c = getFactory().makeNamedType(n.toString());
// if there are no type arguments
if (sc.getTypeArguments().length == 0) {
//we have surely reached the end of the path
assert(!iter.hasNext());
resultType = c; // the result is the raw type
} else {
assert(sc.getTypeArguments().length > 0);
// otherwise, we have type arguments, so we create a parameterized
// type, whose declaration is the raw type c, and whose owner is
// the declaring class of c (if any). This latter fact is indicated
// by passing null as the owner.
// First, we reify the type arguments
Type[] pts = reifyTypeArguments(sc.getTypeArguments());
Type owner = getFactory().makeParameterizedType(c, pts, null);
// phase 2: iterate over remaining simple class types
dollar =false;
while (iter.hasNext()) {
sc = iter.next();
dollar = sc.getDollar();
n.append(dollar?"$":".").append(sc.getName()); // build up raw class name
c = getFactory().makeNamedType(n.toString()); // obtain raw class
pts = reifyTypeArguments(sc.getTypeArguments());// reify params
// Create a parameterized type, based on type args, raw type
// and previous owner
owner = getFactory().makeParameterizedType(c, pts, owner);
}
resultType = owner;
}
}
public void visitArrayTypeSignature(ArrayTypeSignature a){
// extract and reify component type
a.getComponentType().accept(this);
Type ct = resultType;
resultType = getFactory().makeArrayType(ct);
}
public void visitTypeVariableSignature(TypeVariableSignature tv){
resultType = getFactory().findTypeVariable(tv.getIdentifier());
}
public void visitWildcard(Wildcard w){
resultType = getFactory().makeWildcard(w.getUpperBounds(),
w.getLowerBounds());
}
public void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct){
resultType = getFactory().makeNamedType(sct.getName());
}
public void visitBottomSignature(BottomSignature b){
}
public void visitByteSignature(ByteSignature b){
resultType = getFactory().makeByte();
}
public void visitBooleanSignature(BooleanSignature b){
resultType = getFactory().makeBool();
}
public void visitShortSignature(ShortSignature s){
resultType = getFactory().makeShort();
}
public void visitCharSignature(CharSignature c){
resultType = getFactory().makeChar();
}
public void visitIntSignature(IntSignature i){
resultType = getFactory().makeInt();
}
public void visitLongSignature(LongSignature l){
resultType = getFactory().makeLong();
}
public void visitFloatSignature(FloatSignature f){
resultType = getFactory().makeFloat();
}
public void visitDoubleSignature(DoubleSignature d){
resultType = getFactory().makeDouble();
}
public void visitVoidDescriptor(VoidDescriptor v){
resultType = getFactory().makeVoid();
}
}
类型参数 TypeVariable
package java.lang.reflect;
/**
* A common interface for all entities that declare type variables.
*
* @since 1.5
*/
public interface GenericDeclaration extends AnnotatedElement {
/**
* Returns an array of {@code TypeVariable} objects that
* represent the type variables declared by the generic
* declaration represented by this {@code GenericDeclaration}
* object, in declaration order. Returns an array of length 0 if
* the underlying generic declaration declares no type variables.
*
* @return an array of {@code TypeVariable} objects that represent
* the type variables declared by this generic declaration
* @throws GenericSignatureFormatError if the generic
* signature of this generic declaration does not conform to
* the format specified in
* <cite>The Java™ Virtual Machine Specification</cite>
*/
public TypeVariable<?>[] getTypeParameters();
}
package java.lang.reflect;
/**
* TypeVariable is the common superinterface for type variables of kinds.
* A type variable is created the first time it is needed by a reflective
* method, as specified in this package. If a type variable t is referenced
* by a type (i.e, class, interface or annotation type) T, and T is declared
* by the nth enclosing class of T (see JLS 8.1.2), then the creation of t
* requires the resolution (see JVMS 5) of the ith enclosing class of T,
* for i = 0 to n, inclusive. Creating a type variable must not cause the
* creation of its bounds. Repeated creation of a type variable has no effect.
*
* <p>Multiple objects may be instantiated at run-time to
* represent a given type variable. Even though a type variable is
* created only once, this does not imply any requirement to cache
* instances representing the type variable. However, all instances
* representing a type variable must be equal() to each other.
* As a consequence, users of type variables must not rely on the identity
* of instances of classes implementing this interface.
*
* @param <D> the type of generic declaration that declared the
* underlying type variable.
*
* @since 1.5
*/
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
/**
* Returns an array of {@code Type} objects representing the
* upper bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is {@code Object}.
*
* <p>For each upper bound B: <ul> <li>if B is a parameterized
* type or a type variable, it is created, (see {@link
* java.lang.reflect.ParameterizedType ParameterizedType} for the
* details of the creation process for parameterized types).
* <li>Otherwise, B is resolved. </ul>
*
* @throws TypeNotPresentException if any of the
* bounds refers to a non-existent type declaration
* @throws MalformedParameterizedTypeException if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
* @return an array of {@code Type}s representing the upper
* bound(s) of this type variable
*/
Type[] getBounds();
/**
* Returns the {@code GenericDeclaration} object representing the
* generic declaration declared this type variable.
*
* @return the generic declaration declared for this type variable.
*
* @since 1.5
*/
D getGenericDeclaration();
/**
* Returns the name of this type variable, as it occurs in the source code.
*
* @return the name of this type variable, as it appears in the source code
*/
String getName();
/**
* Returns an array of AnnotatedType objects that represent the use of
* types to denote the upper bounds of the type parameter represented by
* this TypeVariable. The order of the objects in the array corresponds to
* the order of the bounds in the declaration of the type parameter.
*
* Returns an array of length 0 if the type parameter declares no bounds.
*
* @return an array of objects representing the upper bounds of the type variable
* @since 1.8
*/
AnnotatedType[] getAnnotatedBounds();
}
以上是关于Java 泛型之 JDK 的底层实现原理的主要内容,如果未能解决你的问题,请参考以下文章