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 }