1 /* 2 * Copyright (c) 2003, 2023, 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 java.util.Arrays; 34 import java.util.StringJoiner; 35 36 37 /** 38 * Implementation of WildcardType interface for core reflection. 39 */ 40 public class WildcardTypeImpl extends LazyReflectiveObjectGenerator 41 implements WildcardType { 42 43 /* 44 * We are required to evaluate the bounds lazily, so we store them as ASTs 45 * until we are first asked for them. This also neatly solves the problem 46 * with F-bounds - you can't reify them before the formal is defined. 47 */ 48 49 /** The upper bounds. Lazily converted from FieldTypeSignature[] to Type[]. */ 50 private volatile Object[] upperBounds; 51 52 /** The lower bounds. Lazily converted from FieldTypeSignature[] to Type[]. */ 53 private volatile Object[] lowerBounds; 54 55 // constructor is private to enforce access through static factory 56 private WildcardTypeImpl(Object[] ubs, 57 Object[] lbs, 58 GenericsFactory f) { 59 super(f); 60 upperBounds = ubs; 61 lowerBounds = lbs; 62 } 63 64 /** 65 * Factory method. 66 * @param ubs - an array of ASTs representing the upper bounds for the type 67 * variable to be created 68 * @param lbs - an array of ASTs representing the lower bounds for the type 69 * variable to be created 70 * @param f - a factory that can be used to manufacture reflective 71 * objects that represent the bounds of this wildcard type 72 * @return a wild card type with the requested bounds and factory 73 */ 74 public static WildcardTypeImpl make(FieldTypeSignature[] ubs, 75 FieldTypeSignature[] lbs, 76 GenericsFactory f) { 77 return new WildcardTypeImpl(ubs, lbs, f); 78 } 79 80 /** 81 * Eager factory method. 82 * @param ubs - an array of types representing the upper bounds 83 * @param lbs - an array of types representing the lower bounds 84 * @return a wild card type with the requested bounds 85 */ 86 public static WildcardTypeImpl make(Type[] ubs, 87 Type[] lbs) { 88 return new WildcardTypeImpl(ubs, lbs, null); 89 } 90 91 /** 92 * Returns an array of {@code Type} objects representing the upper 93 * bound(s) of this type variable. Note that if no upper bound is 94 * explicitly declared, the upper bound is {@code Object}. 95 * 96 * <p>For each upper bound B : 97 * <ul> 98 * <li>if B is a parameterized type or a type variable, it is created, 99 * (see {@link #ParameterizedType} for the details of the creation 100 * process for parameterized types). 101 * <li>Otherwise, B is resolved. 102 * </ul> 103 * 104 * @return an array of Types representing the upper bound(s) of this 105 * type variable 106 * @throws {@code TypeNotPresentException} if any of the 107 * bounds refers to a non-existent type declaration 108 * @throws {@code MalformedParameterizedTypeException} if any of the 109 * bounds refer to a parameterized type that cannot be instantiated 110 * for any reason 111 */ 112 public Type[] getUpperBounds() { 113 Object[] value = upperBounds; 114 if (value instanceof FieldTypeSignature[] sigs) { 115 value = reifyBounds(sigs); 116 upperBounds = value; 117 } 118 return (Type[])value.clone(); 119 } 120 121 /** 122 * Returns an array of {@code Type} objects representing the 123 * lower bound(s) of this type variable. Note that if no lower bound is 124 * explicitly declared, the lower bound is the type of {@code null}. 125 * In this case, a zero length array is returned. 126 * 127 * <p>For each lower bound B : 128 * <ul> 129 * <li>if B is a parameterized type or a type variable, it is created, 130 * (see {@link #ParameterizedType} for the details of the creation 131 * process for parameterized types). 132 * <li>Otherwise, B is resolved. 133 * </ul> 134 * 135 * @return an array of Types representing the lower bound(s) of this 136 * type variable 137 * @throws {@code TypeNotPresentException} if any of the 138 * bounds refers to a non-existent type declaration 139 * @throws {@code MalformedParameterizedTypeException} if any of the 140 * bounds refer to a parameterized type that cannot be instantiated 141 * for any reason 142 */ 143 public Type[] getLowerBounds() { 144 Object[] value = lowerBounds; 145 if (value instanceof FieldTypeSignature[] sigs) { 146 value = reifyBounds(sigs); 147 lowerBounds = value; 148 } 149 return (Type[])value.clone(); 150 } 151 152 public String toString() { 153 Type[] lowerBounds = getLowerBounds(); 154 Type[] bounds = lowerBounds; 155 StringBuilder sb = new StringBuilder(); 156 157 if (lowerBounds.length > 0) 158 sb.append("? super "); 159 else { 160 Type[] upperBounds = getUpperBounds(); 161 if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) { 162 bounds = upperBounds; 163 sb.append("? extends "); 164 } else 165 return "?"; 166 } 167 168 assert bounds.length > 0; 169 170 StringJoiner sj = new StringJoiner(" & "); 171 for(Type bound: bounds) { 172 sj.add(bound.getTypeName()); 173 } 174 sb.append(sj.toString()); 175 176 return sb.toString(); 177 } 178 179 @Override 180 public boolean equals(Object o) { 181 return o instanceof WildcardType that 182 && Arrays.equals(this.getLowerBounds(), that.getLowerBounds()) 183 && Arrays.equals(this.getUpperBounds(), that.getUpperBounds()); 184 } 185 186 @Override 187 public int hashCode() { 188 Type [] lowerBounds = getLowerBounds(); 189 Type [] upperBounds = getUpperBounds(); 190 191 return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds); 192 } 193 }