2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
26 package sun.reflect.generics.reflectiveObjects;
28 import java.lang.annotation.*;
29 import java.lang.reflect.AnnotatedType;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.GenericDeclaration;
33 import java.lang.reflect.Member;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Type;
36 import java.lang.reflect.TypeVariable;
37 import java.util.LinkedHashMap;
39 import java.util.Objects;
40 import sun.reflect.annotation.AnnotationSupport;
41 import sun.reflect.annotation.TypeAnnotationParser;
42 import sun.reflect.annotation.AnnotationType;
43 import sun.reflect.generics.factory.GenericsFactory;
44 import sun.reflect.generics.tree.FieldTypeSignature;
45 import sun.reflect.generics.visitor.Reifier;
46 import sun.reflect.misc.ReflectUtil;
49 * Implementation of <tt>java.lang.reflect.TypeVariable interface
50 * for core reflection.
52 public class TypeVariableImpl<D extends GenericDeclaration>
53 extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
56 // upper bounds - evaluated lazily
57 private Type[] bounds;
59 // The ASTs for the bounds. We are required to evaluate the bounds
60 // lazily, so we store these at least until we are first asked
61 // for the bounds. This also neatly solves the
62 // problem with F-bounds - you can't reify them before the formal
64 private FieldTypeSignature[] boundASTs;
66 // constructor is private to enforce access through static factory
67 private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
70 genericDeclaration = decl;
77 // accessor for ASTs for bounds. Must not be called after
78 // bounds have been evaluated, because we might throw the ASTs
79 // away (but that is not thread-safe, is it?)
80 private FieldTypeSignature[] getBoundASTs() {
81 // check that bounds were not evaluated yet
82 assert(bounds == null);
88 * @param decl - the reflective object that declared the type variable
89 * that this method should create
90 * @param name - the name of the type variable to be returned
91 * @param bs - an array of ASTs representing the bounds for the type
92 * variable to be created
93 * @param f - a factory that can be used to manufacture reflective
94 * objects that represent the bounds of this type variable
95 * @return A type variable with name, bounds, declaration and factory
98 public static <T extends GenericDeclaration>
99 TypeVariableImpl<T> make(T decl, String name,
100 FieldTypeSignature[] bs,
103 if (!((decl instanceof Class) ||
104 (decl instanceof Method) ||
105 (decl instanceof Constructor))) {
106 throw new AssertionError("Unexpected kind of GenericDeclaration" +
107 decl.getClass().toString());
109 return new TypeVariableImpl<T>(decl, name, bs, f);
114 * Returns an array of <tt>Type objects representing the
115 * upper bound(s) of this type variable. Note that if no upper bound is
116 * explicitly declared, the upper bound is <tt>Object.
118 * <p>For each upper bound B:
120 * <li>if B is a parameterized type or a type variable, it is created,
121 * (see {@link #ParameterizedType} for the details of the creation
122 * process for parameterized types).
123 * <li>Otherwise, B is resolved.
126 * @throws <tt>TypeNotPresentException if any of the
127 * bounds refers to a non-existent type declaration
128 * @throws <tt>MalformedParameterizedTypeException if any of the
129 * bounds refer to a parameterized type that cannot be instantiated
131 * @return an array of Types representing the upper bound(s) of this
134 public Type[] getBounds() {
135 // lazily initialize bounds if necessary
136 if (bounds == null) {
137 FieldTypeSignature[] fts = getBoundASTs(); // get AST
138 // allocate result array; note that
139 // keeping ts and bounds separate helps with threads
140 Type[] ts = new Type[fts.length];
141 // iterate over bound trees, reifying each in turn
142 for ( int j = 0; j < fts.length; j++) {
143 Reifier r = getReifier();
145 ts[j] = r.getResult();
149 // could throw away bound ASTs here; thread safety?
151 return bounds.clone(); // return cached bounds
155 * Returns the <tt>GenericDeclaration object representing the
156 * generic declaration that declared this type variable.
158 * @return the generic declaration that declared this type variable.
162 public D getGenericDeclaration(){
163 if (genericDeclaration instanceof Class)
164 ReflectUtil.checkPackageAccess((Class)genericDeclaration);
165 else if ((genericDeclaration instanceof Method) ||
166 (genericDeclaration instanceof Constructor))
167 ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
169 throw new AssertionError("Unexpected kind of GenericDeclaration");
170 return genericDeclaration;
175 * Returns the name of this type variable, as it occurs in the source code.
177 * @return the name of this type variable, as it appears in the source code
179 public String getName() { return name; }
181 public String toString() {return getName();}
184 public boolean equals(Object o) {
185 if (o instanceof TypeVariable &&
186 o.getClass() == TypeVariableImpl.class) {
187 TypeVariable<?> that = (TypeVariable) o;
189 GenericDeclaration thatDecl = that.getGenericDeclaration();
190 String thatName = that.getName();
192 return Objects.equals(genericDeclaration, thatDecl) &&
193 Objects.equals(name, thatName);
200 public int hashCode() {
201 return genericDeclaration.hashCode() ^ name.hashCode();
204 // Implementations of AnnotatedElement methods.
205 @SuppressWarnings("unchecked")
206 public <T extends Annotation> T getAnnotation(Class annotationClass) {
207 Objects.requireNonNull(annotationClass);
208 // T is an Annotation type, the return value of get will be an annotation
209 return (T)mapAnnotations(getAnnotations()).get(annotationClass);
212 public <T extends Annotation> T getDeclaredAnnotation(Class annotationClass) {
213 Objects.requireNonNull(annotationClass);
214 return getAnnotation(annotationClass);
218 public <T extends Annotation> T[] getAnnotationsByType(Class annotationClass) {
219 Objects.requireNonNull(annotationClass);
220 return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
224 public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class annotationClass) {
225 Objects.requireNonNull(annotationClass);
226 return getAnnotationsByType(annotationClass);
229 public Annotation[] getAnnotations() {
230 int myIndex = typeVarIndex();
232 throw new AssertionError("Index must be non-negative.");
233 return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
236 public Annotation[] getDeclaredAnnotations() {
237 return getAnnotations();
240 public AnnotatedType[] getAnnotatedBounds() {
241 return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
242 getGenericDeclaration(),
246 private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
248 // Helpers for annotation methods
249 private int typeVarIndex() {
250 TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
252 for (TypeVariable<?> v : tVars) {
260 private static Map<Class mapAnnotations(Annotation[] annos) {
262 new LinkedHashMap<>();
263 for (Annotation a : annos) {
264 Class<? extends Annotation> klass = a.annotationType();
265 AnnotationType type = AnnotationType.getInstance(klass);
266 if (type.retention() == RetentionPolicy.RUNTIME)
267 if (result.put(klass, a) != null)
268 throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
273 public static void main(String[] args) {
275 TypeVariable typeVar = new TypeVariableImpl(null, null, null, null);