1 /* 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. 4 * 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. 10 * 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). 16 * 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. 20 * 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 23 * questions. 24 */ 25 26 package sun.reflect.generics.reflectiveObjects; 27 28 29 import java.lang.reflect.Type; 30 import java.lang.reflect.WildcardType; 31 import sun.reflect.generics.factory.GenericsFactory; 32 import sun.reflect.generics.tree.FieldTypeSignature; 33 import sun.reflect.generics.visitor.Reifier; 34 import java.util.Arrays; 35 36 37 /** 38 * Implementation of WildcardType interface for core reflection. 39 */ 40 public class WildcardTypeImpl extends LazyReflectiveObjectGenerator 41 implements WildcardType { 42 // upper bounds - evaluated lazily 43 private Type[] upperBounds; 44 // lower bounds - evaluated lazily 45 private Type[] lowerBounds; 46 // The ASTs for the bounds. We are required to evaluate the bounds 47 // lazily, so we store these at least until we are first asked 48 // for the bounds. This also neatly solves the 49 // problem with F-bounds - you can't reify them before the formal 50 // is defined. 51 private FieldTypeSignature[] upperBoundASTs; 52 private FieldTypeSignature[] lowerBoundASTs; 53 54 // constructor is private to enforce access through static factory 55 private WildcardTypeImpl(FieldTypeSignature[] ubs, 56 FieldTypeSignature[] lbs, 57 GenericsFactory f) { 58 super(f); 59 upperBoundASTs = ubs; 60 lowerBoundASTs = lbs; 61 } 62 63 /** 64 * Factory method. 65 * @param ubs - an array of ASTs representing the upper bounds for the type 66 * variable to be created 67 * @param lbs - an array of ASTs representing the lower bounds for the type 68 * variable to be created 69 * @param f - a factory that can be used to manufacture reflective 70 * objects that represent the bounds of this wildcard type 71 * @return a wild card type with the requested bounds and factory 72 */ 73 public static WildcardTypeImpl make(FieldTypeSignature[] ubs, 74 FieldTypeSignature[] lbs, 75 GenericsFactory f) { 76 return new WildcardTypeImpl(ubs, lbs, f); 77 } 78 79 // Accessors 80 81 // accessor for ASTs for upper bounds. Must not be called after upper 82 // bounds have been evaluated, because we might throw the ASTs 83 // away (but that is not thread-safe, is it?) 84 private FieldTypeSignature[] getUpperBoundASTs() { 85 // check that upper bounds were not evaluated yet 86 assert(upperBounds == null); 87 return upperBoundASTs; 88 } 89 // accessor for ASTs for lower bounds. Must not be called after lower 90 // bounds have been evaluated, because we might throw the ASTs 91 // away (but that is not thread-safe, is it?) 92 private FieldTypeSignature[] getLowerBoundASTs() { 93 // check that lower bounds were not evaluated yet 94 assert(lowerBounds == null); 95 return lowerBoundASTs; 96 } 97 98 /** 99 * Returns an array of <tt>Type</tt> objects representing the upper 100 * bound(s) of this type variable. Note that if no upper bound is 101 * explicitly declared, the upper bound is <tt>Object</tt>. 102 * 103 * <p>For each upper bound B : 104 * <ul> 105 * <li>if B is a parameterized type or a type variable, it is created, 106 * (see {@link #ParameterizedType} for the details of the creation 107 * process for parameterized types). 108 * <li>Otherwise, B is resolved. 109 * </ul> 110 * 111 * @return an array of Types representing the upper bound(s) of this 112 * type variable 113 * @throws <tt>TypeNotPresentException</tt> if any of the 114 * bounds refers to a non-existent type declaration 115 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the 116 * bounds refer to a parameterized type that cannot be instantiated 117 * for any reason 118 */ 119 public Type[] getUpperBounds() { 120 // lazily initialize bounds if necessary 121 if (upperBounds == null) { 122 FieldTypeSignature[] fts = getUpperBoundASTs(); // get AST 123 124 // allocate result array; note that 125 // keeping ts and bounds separate helps with threads 126 Type[] ts = new Type[fts.length]; 127 // iterate over bound trees, reifying each in turn 128 for ( int j = 0; j < fts.length; j++) { 129 Reifier r = getReifier(); 130 fts[j].accept(r); 131 ts[j] = r.getResult(); 132 } 133 // cache result 134 upperBounds = ts; 135 // could throw away upper bound ASTs here; thread safety? 136 } 137 return upperBounds.clone(); // return cached bounds 138 } 139 140 /** 141 * Returns an array of <tt>Type</tt> objects representing the 142 * lower bound(s) of this type variable. Note that if no lower bound is 143 * explicitly declared, the lower bound is the type of <tt>null</tt>. 144 * In this case, a zero length array is returned. 145 * 146 * <p>For each lower bound B : 147 * <ul> 148 * <li>if B is a parameterized type or a type variable, it is created, 149 * (see {@link #ParameterizedType} for the details of the creation 150 * process for parameterized types). 151 * <li>Otherwise, B is resolved. 152 * </ul> 153 * 154 * @return an array of Types representing the lower bound(s) of this 155 * type variable 156 * @throws <tt>TypeNotPresentException</tt> if any of the 157 * bounds refers to a non-existent type declaration 158 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the 159 * bounds refer to a parameterized type that cannot be instantiated 160 * for any reason 161 */ 162 public Type[] getLowerBounds() { 163 // lazily initialize bounds if necessary 164 if (lowerBounds == null) { 165 FieldTypeSignature[] fts = getLowerBoundASTs(); // get AST 166 // allocate result array; note that 167 // keeping ts and bounds separate helps with threads 168 Type[] ts = new Type[fts.length]; 169 // iterate over bound trees, reifying each in turn 170 for ( int j = 0; j < fts.length; j++) { 171 Reifier r = getReifier(); 172 fts[j].accept(r); 173 ts[j] = r.getResult(); 174 } 175 // cache result 176 lowerBounds = ts; 177 // could throw away lower bound ASTs here; thread safety? 178 } 179 return lowerBounds.clone(); // return cached bounds 180 } 181 182 public String toString() { 183 Type[] lowerBounds = getLowerBounds(); 184 Type[] bounds = lowerBounds; 185 StringBuilder sb = new StringBuilder(); 186 187 if (lowerBounds.length > 0) 188 sb.append("? super "); 189 else { 190 Type[] upperBounds = getUpperBounds(); 191 if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) { 192 bounds = upperBounds; 193 sb.append("? extends "); 194 } else 195 return "?"; 196 } 197 198 assert bounds.length > 0; 199 200 boolean first = true; 201 for(Type bound: bounds) { 202 if (!first) 203 sb.append(" & "); 204 205 first = false; 206 sb.append(bound.getTypeName()); 207 } 208 return sb.toString(); 209 } 210 211 @Override 212 public boolean equals(Object o) { 213 if (o instanceof WildcardType) { 214 WildcardType that = (WildcardType) o; 215 return 216 Arrays.equals(this.getLowerBounds(), 217 that.getLowerBounds()) && 218 Arrays.equals(this.getUpperBounds(), 219 that.getUpperBounds()); 220 } else 221 return false; 222 } 223 224 @Override 225 public int hashCode() { 226 Type [] lowerBounds = getLowerBounds(); 227 Type [] upperBounds = getUpperBounds(); 228 229 return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds); 230 } 231 }