feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.Objects;
/**
* Implementation of GenericArrayType interface for core reflection.
*/
public class GenericArrayTypeImpl
implements GenericArrayType {
private final Type genericComponentType;
// private constructor enforces use of static factory
private GenericArrayTypeImpl(Type ct) {
genericComponentType = ct;
}
/**
* Factory method.
* @param ct - the desired component type of the generic array type
* being created
* @return a generic array type with the desired component type
*/
public static GenericArrayTypeImpl make(Type ct) {
return new GenericArrayTypeImpl(ct);
}
/**
* Returns a <tt>Type</tt> object representing the component type
* of this array.
*
* @return a <tt>Type</tt> object representing the component type
* of this array
* @since 1.5
*/
public Type getGenericComponentType() {
return genericComponentType; // return cached component type
}
public String toString() {
Type componentType = getGenericComponentType();
StringBuilder sb = new StringBuilder();
if (componentType instanceof Class)
sb.append(((Class)componentType).getName() );
else
sb.append(componentType.toString());
sb.append("[]");
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (o instanceof GenericArrayType) {
GenericArrayType that = (GenericArrayType) o;
return Objects.equals(genericComponentType, that.getGenericComponentType());
} else
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(genericComponentType);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.visitor.Reifier;
/**
* Common infrastructure for things that lazily generate reflective generics
* objects.
* <p> In all these cases, one needs produce a visitor that will, on demand,
* traverse the stored AST(s) and reify them into reflective objects.
* The visitor needs to be initialized with a factory, which will be
* provided when the instance is initialized.
* The factory should be cached.
*
*/
public abstract class LazyReflectiveObjectGenerator {
private final GenericsFactory factory; // cached factory
protected LazyReflectiveObjectGenerator(GenericsFactory f) {
factory = f;
}
// accessor for factory
private GenericsFactory getFactory() {
return factory;
}
// produce a reifying visitor (could this be typed as a TypeTreeVisitor?
protected Reifier getReifier(){return Reifier.make(getFactory());}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
/** Temporary class used to indicate missing functionality */
public class NotImplementedException extends RuntimeException {
private static final long serialVersionUID = -9177857708926624790L;
}

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
import sun.reflect.generics.tree.FieldTypeSignature;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.Objects;
/** Implementing class for ParameterizedType interface. */
public class ParameterizedTypeImpl implements ParameterizedType {
private final Type[] actualTypeArguments;
private final Class<?> rawType;
private final Type ownerType;
private ParameterizedTypeImpl(Class<?> rawType,
Type[] actualTypeArguments,
Type ownerType) {
this.actualTypeArguments = actualTypeArguments;
this.rawType = rawType;
this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
validateConstructorArguments();
}
private void validateConstructorArguments() {
TypeVariable<?>[] formals = rawType.getTypeParameters();
// check correct arity of actual type args
if (formals.length != actualTypeArguments.length){
throw new MalformedParameterizedTypeException();
}
for (int i = 0; i < actualTypeArguments.length; i++) {
// check actuals against formals' bounds
}
}
/**
* Static factory. Given a (generic) class, actual type arguments
* and an owner type, creates a parameterized type.
* This class can be instantiated with a a raw type that does not
* represent a generic type, provided the list of actual type
* arguments is empty.
* If the ownerType argument is null, the declaring class of the
* raw type is used as the owner type.
* <p> This method throws a MalformedParameterizedTypeException
* under the following circumstances:
* If the number of actual type arguments (i.e., the size of the
* array <tt>typeArgs</tt>) does not correspond to the number of
* formal type arguments.
* If any of the actual type arguments is not an instance of the
* bounds on the corresponding formal.
* @param rawType the Class representing the generic type declaration being
* instantiated
* @param actualTypeArguments - a (possibly empty) array of types
* representing the actual type arguments to the parameterized type
* @param ownerType - the enclosing type, if known.
* @return An instance of <tt>ParameterizedType</tt>
* @throws MalformedParameterizedTypeException - if the instantiation
* is invalid
*/
public static ParameterizedTypeImpl make(Class<?> rawType,
Type[] actualTypeArguments,
Type ownerType) {
return new ParameterizedTypeImpl(rawType, actualTypeArguments,
ownerType);
}
/**
* Returns an array of <tt>Type</tt> objects representing the actual type
* arguments to this type.
*
* <p>Note that in some cases, the returned array be empty. This can occur
* if this type represents a non-parameterized type nested within
* a parameterized type.
*
* @return an array of <tt>Type</tt> objects representing the actual type
* arguments to this type
* @throws <tt>TypeNotPresentException</tt> if any of the
* actual type arguments refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* actual type parameters refer to a parameterized type that cannot
* be instantiated for any reason
* @since 1.5
*/
public Type[] getActualTypeArguments() {
return actualTypeArguments.clone();
}
/**
* Returns the <tt>Type</tt> object representing the class or interface
* that declared this type.
*
* @return the <tt>Type</tt> object representing the class or interface
* that declared this type
*/
public Class<?> getRawType() {
return rawType;
}
/**
* Returns a <tt>Type</tt> object representing the type that this type
* is a member of. For example, if this type is <tt>O<T>.I<S></tt>,
* return a representation of <tt>O<T></tt>.
*
* <p>If this type is a top-level type, <tt>null</tt> is returned.
*
* @return a <tt>Type</tt> object representing the type that
* this type is a member of. If this type is a top-level type,
* <tt>null</tt> is returned
* @throws <tt>TypeNotPresentException</tt> if the owner type
* refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if the owner type
* refers to a parameterized type that cannot be instantiated
* for any reason
*
*/
public Type getOwnerType() {
return ownerType;
}
/*
* From the JavaDoc for java.lang.reflect.ParameterizedType
* "Instances of classes that implement this interface must
* implement an equals() method that equates any two instances
* that share the same generic type declaration and have equal
* type parameters."
*/
@Override
public boolean equals(Object o) {
if (o instanceof ParameterizedType) {
// Check that information is equivalent
ParameterizedType that = (ParameterizedType) o;
if (this == that)
return true;
Type thatOwner = that.getOwnerType();
Type thatRawType = that.getRawType();
if (false) { // Debugging
boolean ownerEquality = (ownerType == null ?
thatOwner == null :
ownerType.equals(thatOwner));
boolean rawEquality = (rawType == null ?
thatRawType == null :
rawType.equals(thatRawType));
boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
for (Type t : actualTypeArguments) {
System.out.printf("\t\t%s%s%n", t, t.getClass());
}
System.out.printf("\towner %s\traw %s\ttypeArg %s%n",
ownerEquality, rawEquality, typeArgEquality);
return ownerEquality && rawEquality && typeArgEquality;
}
return
Objects.equals(ownerType, thatOwner) &&
Objects.equals(rawType, thatRawType) &&
Arrays.equals(actualTypeArguments, // avoid clone
that.getActualTypeArguments());
} else
return false;
}
@Override
public int hashCode() {
return
Arrays.hashCode(actualTypeArguments) ^
Objects.hashCode(ownerType) ^
Objects.hashCode(rawType);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (ownerType != null) {
if (ownerType instanceof Class)
sb.append(((Class)ownerType).getName());
else
sb.append(ownerType.toString());
sb.append("$");
if (ownerType instanceof ParameterizedTypeImpl) {
// Find simple name of nested type by removing the
// shared prefix with owner.
sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$",
""));
} else
sb.append(rawType.getSimpleName());
} else
sb.append(rawType.getName());
if (actualTypeArguments != null &&
actualTypeArguments.length > 0) {
sb.append("<");
boolean first = true;
for(Type t: actualTypeArguments) {
if (!first)
sb.append(", ");
sb.append(t.getTypeName());
first = false;
}
sb.append(">");
}
return sb.toString();
}
}

View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
import java.lang.annotation.*;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import sun.reflect.annotation.AnnotationSupport;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.annotation.AnnotationType;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
import sun.reflect.misc.ReflectUtil;
/**
* Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface
* for core reflection.
*/
public class TypeVariableImpl<D extends GenericDeclaration>
extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
D genericDeclaration;
private String name;
// upper bounds - evaluated lazily
private Type[] bounds;
// The ASTs for the bounds. We are required to evaluate the bounds
// lazily, so we store these at least until we are first asked
// for the bounds. This also neatly solves the
// problem with F-bounds - you can't reify them before the formal
// is defined.
private FieldTypeSignature[] boundASTs;
// constructor is private to enforce access through static factory
private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
GenericsFactory f) {
super(f);
genericDeclaration = decl;
name = n;
boundASTs = bs;
}
// Accessors
// accessor for ASTs for bounds. Must not be called after
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getBoundASTs() {
// check that bounds were not evaluated yet
assert(bounds == null);
return boundASTs;
}
/**
* Factory method.
* @param decl - the reflective object that declared the type variable
* that this method should create
* @param name - the name of the type variable to be returned
* @param bs - an array of ASTs representing the bounds for the type
* variable to be created
* @param f - a factory that can be used to manufacture reflective
* objects that represent the bounds of this type variable
* @return A type variable with name, bounds, declaration and factory
* specified
*/
public static <T extends GenericDeclaration>
TypeVariableImpl<T> make(T decl, String name,
FieldTypeSignature[] bs,
GenericsFactory f) {
if (!((decl instanceof Class) ||
(decl instanceof Method) ||
(decl instanceof Constructor))) {
throw new AssertionError("Unexpected kind of GenericDeclaration" +
decl.getClass().toString());
}
return new TypeVariableImpl<T>(decl, name, bs, f);
}
/**
* Returns an array of <tt>Type</tt> objects representing the
* upper bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is <tt>Object</tt>.
*
* <p>For each upper bound B:
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @throws <tt>TypeNotPresentException</tt> if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
* @return an array of Types representing the upper bound(s) of this
* type variable
*/
public Type[] getBounds() {
// lazily initialize bounds if necessary
if (bounds == null) {
FieldTypeSignature[] fts = getBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
bounds = ts;
// could throw away bound ASTs here; thread safety?
}
return bounds.clone(); // return cached bounds
}
/**
* Returns the <tt>GenericDeclaration</tt> object representing the
* generic declaration that declared this type variable.
*
* @return the generic declaration that declared this type variable.
*
* @since 1.5
*/
public D getGenericDeclaration(){
if (genericDeclaration instanceof Class)
ReflectUtil.checkPackageAccess((Class)genericDeclaration);
else if ((genericDeclaration instanceof Method) ||
(genericDeclaration instanceof Constructor))
ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
else
throw new AssertionError("Unexpected kind of GenericDeclaration");
return genericDeclaration;
}
/**
* 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
*/
public String getName() { return name; }
public String toString() {return getName();}
@Override
public boolean equals(Object o) {
if (o instanceof TypeVariable &&
o.getClass() == TypeVariableImpl.class) {
TypeVariable<?> that = (TypeVariable<?>) o;
GenericDeclaration thatDecl = that.getGenericDeclaration();
String thatName = that.getName();
return Objects.equals(genericDeclaration, thatDecl) &&
Objects.equals(name, thatName);
} else
return false;
}
@Override
public int hashCode() {
return genericDeclaration.hashCode() ^ name.hashCode();
}
// Implementations of AnnotatedElement methods.
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
// T is an Annotation type, the return value of get will be an annotation
return (T)mapAnnotations(getAnnotations()).get(annotationClass);
}
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
return getAnnotation(annotationClass);
}
@Override
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
}
@Override
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
return getAnnotationsByType(annotationClass);
}
public Annotation[] getAnnotations() {
int myIndex = typeVarIndex();
if (myIndex < 0)
throw new AssertionError("Index must be non-negative.");
return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
}
public Annotation[] getDeclaredAnnotations() {
return getAnnotations();
}
public AnnotatedType[] getAnnotatedBounds() {
return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
getGenericDeclaration(),
typeVarIndex());
}
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
// Helpers for annotation methods
private int typeVarIndex() {
TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
int i = -1;
for (TypeVariable<?> v : tVars) {
i++;
if (equals(v))
return i;
}
return -1;
}
private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
Map<Class<? extends Annotation>, Annotation> result =
new LinkedHashMap<>();
for (Annotation a : annos) {
Class<? extends Annotation> klass = a.annotationType();
AnnotationType type = AnnotationType.getInstance(klass);
if (type.retention() == RetentionPolicy.RUNTIME)
if (result.put(klass, a) != null)
throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
}
return result;
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.reflect.generics.reflectiveObjects;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier;
import java.util.Arrays;
/**
* Implementation of WildcardType interface for core reflection.
*/
public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
implements WildcardType {
// upper bounds - evaluated lazily
private Type[] upperBounds;
// lower bounds - evaluated lazily
private Type[] lowerBounds;
// The ASTs for the bounds. We are required to evaluate the bounds
// lazily, so we store these at least until we are first asked
// for the bounds. This also neatly solves the
// problem with F-bounds - you can't reify them before the formal
// is defined.
private FieldTypeSignature[] upperBoundASTs;
private FieldTypeSignature[] lowerBoundASTs;
// constructor is private to enforce access through static factory
private WildcardTypeImpl(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs,
GenericsFactory f) {
super(f);
upperBoundASTs = ubs;
lowerBoundASTs = lbs;
}
/**
* Factory method.
* @param ubs - an array of ASTs representing the upper bounds for the type
* variable to be created
* @param lbs - an array of ASTs representing the lower bounds for the type
* variable to be created
* @param f - a factory that can be used to manufacture reflective
* objects that represent the bounds of this wildcard type
* @return a wild card type with the requested bounds and factory
*/
public static WildcardTypeImpl make(FieldTypeSignature[] ubs,
FieldTypeSignature[] lbs,
GenericsFactory f) {
return new WildcardTypeImpl(ubs, lbs, f);
}
// Accessors
// accessor for ASTs for upper bounds. Must not be called after upper
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getUpperBoundASTs() {
// check that upper bounds were not evaluated yet
assert(upperBounds == null);
return upperBoundASTs;
}
// accessor for ASTs for lower bounds. Must not be called after lower
// bounds have been evaluated, because we might throw the ASTs
// away (but that is not thread-safe, is it?)
private FieldTypeSignature[] getLowerBoundASTs() {
// check that lower bounds were not evaluated yet
assert(lowerBounds == null);
return lowerBoundASTs;
}
/**
* Returns an array of <tt>Type</tt> objects representing the upper
* bound(s) of this type variable. Note that if no upper bound is
* explicitly declared, the upper bound is <tt>Object</tt>.
*
* <p>For each upper bound B :
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @return an array of Types representing the upper bound(s) of this
* type variable
* @throws <tt>TypeNotPresentException</tt> if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
public Type[] getUpperBounds() {
// lazily initialize bounds if necessary
if (upperBounds == null) {
FieldTypeSignature[] fts = getUpperBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
upperBounds = ts;
// could throw away upper bound ASTs here; thread safety?
}
return upperBounds.clone(); // return cached bounds
}
/**
* Returns an array of <tt>Type</tt> objects representing the
* lower bound(s) of this type variable. Note that if no lower bound is
* explicitly declared, the lower bound is the type of <tt>null</tt>.
* In this case, a zero length array is returned.
*
* <p>For each lower bound B :
* <ul>
* <li>if B is a parameterized type or a type variable, it is created,
* (see {@link #ParameterizedType} for the details of the creation
* process for parameterized types).
* <li>Otherwise, B is resolved.
* </ul>
*
* @return an array of Types representing the lower bound(s) of this
* type variable
* @throws <tt>TypeNotPresentException</tt> if any of the
* bounds refers to a non-existent type declaration
* @throws <tt>MalformedParameterizedTypeException</tt> if any of the
* bounds refer to a parameterized type that cannot be instantiated
* for any reason
*/
public Type[] getLowerBounds() {
// lazily initialize bounds if necessary
if (lowerBounds == null) {
FieldTypeSignature[] fts = getLowerBoundASTs(); // get AST
// allocate result array; note that
// keeping ts and bounds separate helps with threads
Type[] ts = new Type[fts.length];
// iterate over bound trees, reifying each in turn
for ( int j = 0; j < fts.length; j++) {
Reifier r = getReifier();
fts[j].accept(r);
ts[j] = r.getResult();
}
// cache result
lowerBounds = ts;
// could throw away lower bound ASTs here; thread safety?
}
return lowerBounds.clone(); // return cached bounds
}
public String toString() {
Type[] lowerBounds = getLowerBounds();
Type[] bounds = lowerBounds;
StringBuilder sb = new StringBuilder();
if (lowerBounds.length > 0)
sb.append("? super ");
else {
Type[] upperBounds = getUpperBounds();
if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) {
bounds = upperBounds;
sb.append("? extends ");
} else
return "?";
}
assert bounds.length > 0;
boolean first = true;
for(Type bound: bounds) {
if (!first)
sb.append(" & ");
first = false;
sb.append(bound.getTypeName());
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (o instanceof WildcardType) {
WildcardType that = (WildcardType) o;
return
Arrays.equals(this.getLowerBounds(),
that.getLowerBounds()) &&
Arrays.equals(this.getUpperBounds(),
that.getUpperBounds());
} else
return false;
}
@Override
public int hashCode() {
Type [] lowerBounds = getLowerBounds();
Type [] upperBounds = getUpperBounds();
return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds);
}
}