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(FieldTypeSignature[] ubs,
57 FieldTypeSignature[] 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 * Returns an array of {@code Type} objects representing the upper
82 * bound(s) of this type variable. Note that if no upper bound is
83 * explicitly declared, the upper bound is {@code Object}.
84 *
85 * <p>For each upper bound B :
86 * <ul>
87 * <li>if B is a parameterized type or a type variable, it is created,
88 * (see {@link #ParameterizedType} for the details of the creation
89 * process for parameterized types).
90 * <li>Otherwise, B is resolved.
91 * </ul>
92 *
93 * @return an array of Types representing the upper bound(s) of this
94 * type variable
95 * @throws {@code TypeNotPresentException} if any of the
96 * bounds refers to a non-existent type declaration
97 * @throws {@code MalformedParameterizedTypeException} if any of the
98 * bounds refer to a parameterized type that cannot be instantiated
99 * for any reason
100 */
101 public Type[] getUpperBounds() {
102 Object[] value = upperBounds;
103 if (value instanceof FieldTypeSignature[] sigs) {
104 value = reifyBounds(sigs);
105 upperBounds = value;
106 }
107 return (Type[])value.clone();
108 }
109
110 /**
111 * Returns an array of {@code Type} objects representing the
112 * lower bound(s) of this type variable. Note that if no lower bound is
113 * explicitly declared, the lower bound is the type of {@code null}.
114 * In this case, a zero length array is returned.
115 *
116 * <p>For each lower bound B :
117 * <ul>
118 * <li>if B is a parameterized type or a type variable, it is created,
119 * (see {@link #ParameterizedType} for the details of the creation
120 * process for parameterized types).
121 * <li>Otherwise, B is resolved.
122 * </ul>
123 *
124 * @return an array of Types representing the lower bound(s) of this
125 * type variable
126 * @throws {@code TypeNotPresentException} if any of the
127 * bounds refers to a non-existent type declaration
128 * @throws {@code MalformedParameterizedTypeException} if any of the
129 * bounds refer to a parameterized type that cannot be instantiated
130 * for any reason
131 */
132 public Type[] getLowerBounds() {
133 Object[] value = lowerBounds;
134 if (value instanceof FieldTypeSignature[] sigs) {
135 value = reifyBounds(sigs);
136 lowerBounds = value;
137 }
138 return (Type[])value.clone();
139 }
140
141 public String toString() {
142 Type[] lowerBounds = getLowerBounds();
143 Type[] bounds = lowerBounds;
144 StringBuilder sb = new StringBuilder();
145
146 if (lowerBounds.length > 0)
147 sb.append("? super ");
148 else {
149 Type[] upperBounds = getUpperBounds();
150 if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) {
151 bounds = upperBounds;
152 sb.append("? extends ");
153 } else
154 return "?";
155 }
156
157 assert bounds.length > 0;
158
159 StringJoiner sj = new StringJoiner(" & ");
160 for(Type bound: bounds) {
161 sj.add(bound.getTypeName());
162 }
163 sb.append(sj.toString());
164
165 return sb.toString();
166 }
167
168 @Override
169 public boolean equals(Object o) {
170 return o instanceof WildcardType that
171 && Arrays.equals(this.getLowerBounds(), that.getLowerBounds())
172 && Arrays.equals(this.getUpperBounds(), that.getUpperBounds());
173 }
174
175 @Override
176 public int hashCode() {
177 Type [] lowerBounds = getLowerBounds();
178 Type [] upperBounds = getUpperBounds();
179
180 return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds);
181 }
182 }