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 package java.lang.constant;
26
27 import java.lang.invoke.MethodHandles;
28
29 import static java.lang.constant.ConstantUtils.*;
30 import static java.util.Objects.requireNonNull;
31
32 /**
33 * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
34 * interface, or array type. A {@linkplain ReferenceClassDescImpl} corresponds to a
35 * {@code Constant_Class_info} entry in the constant pool of a classfile.
36 */
37 final class ReferenceClassDescImpl implements ClassDesc {
38 private final String descriptor;
39
40 /**
41 * Creates a {@linkplain ClassDesc} from a descriptor string for a class or
42 * interface type or an array type.
43 *
44 * @param descriptor a field descriptor string for a class or interface type
45 * @throws IllegalArgumentException if the descriptor string is not a valid
46 * field descriptor string, or does not describe a class or interface type
47 * @jvms 4.3.2 Field Descriptors
48 */
49 ReferenceClassDescImpl(String descriptor) {
50 requireNonNull(descriptor);
51 int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length(), false);
52 if (len == 0 || len == 1
53 || len != descriptor.length())
54 throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
55 this.descriptor = descriptor;
56 }
57
58 @Override
59 public String descriptorString() {
60 return descriptor;
61 }
62
63 @Override
64 public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
65 throws ReflectiveOperationException {
66 if (isArray()) {
67 if (isPrimitiveArray()) {
68 return lookup.findClass(descriptor);
69 }
71 int depth = ConstantUtils.arrayDepth(descriptor);
72 Class<?> clazz = lookup.findClass(internalToBinary(descriptor.substring(depth + 1, descriptor.length() - 1)));
73 for (int i = 0; i < depth; i++)
74 clazz = clazz.arrayType();
75 return clazz;
76 }
77 return lookup.findClass(internalToBinary(dropFirstAndLastChar(descriptor)));
78 }
79
80 /**
81 * Whether the descriptor is one of a primitive array, given this is
82 * already a valid reference type descriptor.
83 */
84 private boolean isPrimitiveArray() {
85 // All L-type descriptors must end with a semicolon; same for reference
86 // arrays, leaving primitive arrays the only ones without a final semicolon
87 return descriptor.charAt(descriptor.length() - 1) != ';';
88 }
89
90 /**
91 * Returns {@code true} if this {@linkplain ReferenceClassDescImpl} is
92 * equal to another {@linkplain ReferenceClassDescImpl}. Equality is
93 * determined by the two class descriptors having equal class descriptor
94 * strings.
95 *
96 * @param o the {@code ClassDesc} to compare to this
97 * {@code ClassDesc}
98 * @return {@code true} if the specified {@code ClassDesc}
99 * is equal to this {@code ClassDesc}.
100 */
101 @Override
102 public boolean equals(Object o) {
103 if (this == o) return true;
104 if (o == null || getClass() != o.getClass()) return false;
105
106 ClassDesc constant = (ClassDesc) o;
107 return descriptor.equals(constant.descriptorString());
108 }
109
110 @Override
111 public int hashCode() {
112 return descriptor.hashCode();
|
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 package java.lang.constant;
26
27 import java.lang.invoke.MethodHandles;
28
29 import static java.lang.constant.ConstantUtils.*;
30 import static java.util.Objects.requireNonNull;
31
32 /**
33 * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class,
34 * interface, or array type. A {@linkplain ClassDescImpl} corresponds to a
35 * {@code Constant_Class_info} entry in the constant pool of a classfile.
36 */
37 final class ClassDescImpl implements ClassDesc {
38 private final String descriptor;
39
40 /**
41 * Creates a {@linkplain ClassDesc} from a descriptor string for a class or
42 * interface type or an array type.
43 *
44 * @param descriptor a field descriptor string for a class or interface type
45 * @throws IllegalArgumentException if the descriptor string is not a valid
46 * field descriptor string, or does not describe a class or interface type
47 * @jvms 4.3.2 Field Descriptors
48 */
49 ClassDescImpl(String descriptor) {
50 requireNonNull(descriptor);
51 int len = ConstantUtils.skipOverFieldSignature(descriptor, 0, descriptor.length(), false);
52 if (len == 0 || len == 1
53 || len != descriptor.length())
54 throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor));
55 this.descriptor = descriptor;
56 }
57
58 @Override
59 public String descriptorString() {
60 return descriptor;
61 }
62
63 @Override
64 public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup)
65 throws ReflectiveOperationException {
66 if (isArray()) {
67 if (isPrimitiveArray()) {
68 return lookup.findClass(descriptor);
69 }
71 int depth = ConstantUtils.arrayDepth(descriptor);
72 Class<?> clazz = lookup.findClass(internalToBinary(descriptor.substring(depth + 1, descriptor.length() - 1)));
73 for (int i = 0; i < depth; i++)
74 clazz = clazz.arrayType();
75 return clazz;
76 }
77 return lookup.findClass(internalToBinary(dropFirstAndLastChar(descriptor)));
78 }
79
80 /**
81 * Whether the descriptor is one of a primitive array, given this is
82 * already a valid reference type descriptor.
83 */
84 private boolean isPrimitiveArray() {
85 // All L-type descriptors must end with a semicolon; same for reference
86 // arrays, leaving primitive arrays the only ones without a final semicolon
87 return descriptor.charAt(descriptor.length() - 1) != ';';
88 }
89
90 /**
91 * Returns {@code true} if this {@linkplain ClassDescImpl} is
92 * equal to another {@linkplain ClassDescImpl}. Equality is
93 * determined by the two class descriptors having equal class descriptor
94 * strings.
95 *
96 * @param o the {@code ClassDesc} to compare to this
97 * {@code ClassDesc}
98 * @return {@code true} if the specified {@code ClassDesc}
99 * is equal to this {@code ClassDesc}.
100 */
101 @Override
102 public boolean equals(Object o) {
103 if (this == o) return true;
104 if (o == null || getClass() != o.getClass()) return false;
105
106 ClassDesc constant = (ClassDesc) o;
107 return descriptor.equals(constant.descriptorString());
108 }
109
110 @Override
111 public int hashCode() {
112 return descriptor.hashCode();
|