< prev index next >
src/java.base/share/classes/java/lang/Class.java
Print this page
*** 161,174 ****
* hidden classes; all kinds of interface, including annotation types,
* may be hidden interfaces.
*
* The {@linkplain #getName() name of a hidden class or interface} is
* not a <a href="ClassLoader.html#binary-name">binary name</a>,
! * which means that a hidden class or interface cannot be
! * referenced by the constant pools of other classes and interfaces,
! * and cannot be discovered by {@link #forName Class::forName} or
! * {@link ClassLoader#loadClass(String, boolean) ClassLoader::loadClass}.
*
* A hidden class or interface is never an array class, but may be
* the element type of an array. In all other respects, the fact that
* a class or interface is hidden has no bearing on the characteristics
* exposed by the methods of class {@code Class}.
--- 161,182 ----
* hidden classes; all kinds of interface, including annotation types,
* may be hidden interfaces.
*
* The {@linkplain #getName() name of a hidden class or interface} is
* not a <a href="ClassLoader.html#binary-name">binary name</a>,
! * which means the following:
! * <ul>
! * <li>A hidden class or interface cannot be referenced by the constant pools
! * of other classes and interfaces.
! * <li>A hidden class or interface cannot be described in
! * {@linkplain java.lang.constant.ConstantDesc <em>nominal form</em>} by
! * {@link #describeConstable() Class::describeConstable},
! * {@link ClassDesc#of(String) ClassDesc::of}, or
! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor}.
! * <li>A hidden class or interface cannot be discovered by {@link #forName Class::forName}
! * or {@link ClassLoader#loadClass(String, boolean) ClassLoader::loadClass}.
! * </ul>
*
* A hidden class or interface is never an array class, but may be
* the element type of an array. In all other respects, the fact that
* a class or interface is hidden has no bearing on the characteristics
* exposed by the methods of class {@code Class}.
*** 1063,1076 ****
* @jls 6.7 Fully Qualified Names
*/
public String getPackageName() {
String pn = this.packageName;
if (pn == null) {
! Class<?> c = this;
! while (c.isArray()) {
! c = c.getComponentType();
! }
if (c.isPrimitive()) {
pn = "java.lang";
} else {
String cn = c.getName();
int dot = cn.lastIndexOf('.');
--- 1071,1081 ----
* @jls 6.7 Fully Qualified Names
*/
public String getPackageName() {
String pn = this.packageName;
if (pn == null) {
! Class<?> c = isArray() ? elementType() : this;
if (c.isPrimitive()) {
pn = "java.lang";
} else {
String cn = c.getName();
int dot = cn.lastIndexOf('.');
*** 1224,1233 ****
--- 1229,1252 ----
}
}
private final Class<?> componentType;
+ /*
+ * Returns the {@code Class} representing the element type of an array class.
+ * If this class does not represent an array class, then this method returns
+ * {@code null}.
+ */
+ private Class<?> elementType() {
+ if (!isArray()) return null;
+
+ Class<?> c = this;
+ while (c.isArray()) {
+ c = c.getComponentType();
+ }
+ return c;
+ }
/**
* Returns the Java language modifiers for this class or interface, encoded
* in an integer. The modifiers consist of the Java Virtual Machine's
* constants for {@code public}, {@code protected},
*** 3021,3034 ****
* Add a package name prefix if the name is not absolute Remove leading "/"
* if name is absolute
*/
private String resolveName(String name) {
if (!name.startsWith("/")) {
! Class<?> c = this;
! while (c.isArray()) {
! c = c.getComponentType();
! }
String baseName = c.getPackageName();
if (baseName != null && !baseName.isEmpty()) {
name = baseName.replace('.', '/') + "/" + name;
}
} else {
--- 3040,3050 ----
* Add a package name prefix if the name is not absolute Remove leading "/"
* if name is absolute
*/
private String resolveName(String name) {
if (!name.startsWith("/")) {
! Class<?> c = isArray() ? elementType() : this;
String baseName = c.getPackageName();
if (baseName != null && !baseName.isEmpty()) {
name = baseName.replace('.', '/') + "/" + name;
}
} else {
*** 4212,4239 ****
}
return members;
}
/**
! * Returns the type descriptor string for this class.
! * <p>
! * Note that this is not a strict inverse of {@link #forName};
* distinct classes which share a common name but have different class loaders
* will have identical descriptor strings.
*
! * @return the type descriptor representation
* @jvms 4.3.2 Field Descriptors
* @since 12
*/
@Override
public String descriptorString() {
if (isPrimitive())
return Wrapper.forPrimitiveType(this).basicTypeString();
! else if (isArray()) {
return "[" + componentType.descriptorString();
! }
! else {
return "L" + getName().replace('.', '/') + ";";
}
}
/**
--- 4228,4299 ----
}
return members;
}
/**
! * Returns the descriptor string of the entity (class, interface, array class,
! * primitive type, or {@code void}) represented by this {@code Class} object.
! *
! * <p> If this {@code Class} object represents a class or interface,
! * not an array class, then:
! * <ul>
! * <li> If the class or interface is not {@linkplain Class#isHidden() hidden},
! * then the result is a field descriptor string (JVMS {@jvms 4.3.2})
! * for the class or interface. A {@link ClassDesc ClassDesc}
! * can be created from the result descriptor string via
! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor}.
! * <li> If the class or interface is {@linkplain Class#isHidden() hidden},
! * then the result is a string of the form: {@code "L" + N + "." + <suffix> + ";"}
! * where {@code N} is the <a href="ClassLoader.html#binary-name">binary name</a>
! * encoded in internal form indicated by the {@code class} file passed to
! * {@link MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...)
! * Lookup::defineHiddenClass}, and {@code <suffix>} is an unqualified name.
! * A hidden class or interface has no {@linkplain ClassDesc nominal descriptor}.
! * </ul>
! *
! * <p> If this {@code Class} object represents an array class, then
! * the result is a string consisting of one or more '{@code [}' characters
! * representing the depth of the array nesting, followed by the
! * descriptor string of the element type.
! * <ul>
! * <li> If the element type is not a {@linkplain Class#isHidden() hidden} class
! * or interface, then this array class can be described nominally and a
! * {@link ClassDesc ClassDesc} can be created via
! * {@link ClassDesc#ofDescriptor(String) ClassDesc::ofDescriptor}
! * from the result field descriptor string.
! * <li> If the element type is a {@linkplain Class#isHidden() hidden} class or
! * interface, then this array class cannot be described nominally and
! * no {@code ClassDesc} can be created from the result string.
! * </ul>
! *
! * <p> If this {@code Class} object represents a primitive type or
! * {@code void}, then the result is a field descriptor string which
! * is a one-letter code corresponding to a primitive type or {@code void}
! * ({@code "B", "C", "D", "F", "I", "J", "S", "Z", "V"}) (JVMS {@jvms 4.3.2}).
! *
! * @apiNote
! * This is not a strict inverse of {@link #forName};
* distinct classes which share a common name but have different class loaders
* will have identical descriptor strings.
*
! * @return the descriptor string for this {@code Class} object
* @jvms 4.3.2 Field Descriptors
* @since 12
*/
@Override
public String descriptorString() {
if (isPrimitive())
return Wrapper.forPrimitiveType(this).basicTypeString();
!
! if (isArray()) {
return "[" + componentType.descriptorString();
! } else if (isHidden()) {
! String name = getName();
! int index = name.indexOf('/');
! return "L" + name.substring(0, index).replace('.', '/')
! + "." + name.substring(index+1, name.length()) + ";";
! } else {
return "L" + getName().replace('.', '/') + ";";
}
}
/**
*** 4272,4282 ****
* or an empty {@link Optional} if one cannot be constructed.
* @since 12
*/
@Override
public Optional<ClassDesc> describeConstable() {
! return Optional.of(ClassDesc.ofDescriptor(descriptorString()));
}
/**
* Returns {@code true} if and only if the underlying class is a hidden class.
*
--- 4332,4344 ----
* or an empty {@link Optional} if one cannot be constructed.
* @since 12
*/
@Override
public Optional<ClassDesc> describeConstable() {
! Class<?> c = isArray() ? elementType() : this;
! return c.isHidden() ? Optional.empty()
! : Optional.of(ClassDesc.ofDescriptor(descriptorString()));
}
/**
* Returns {@code true} if and only if the underlying class is a hidden class.
*
< prev index next >