< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page

        

*** 56,66 **** import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; - import java.util.Set; import java.util.StringJoiner; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; --- 56,65 ----
*** 187,197 **** * this method returns "class " followed by {@code getName}. * * @return a string representation of this class object. */ public String toString() { ! return (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + getName(); } /** * Returns a string describing this {@code Class}, including --- 186,197 ---- * this method returns "class " followed by {@code getName}. * * @return a string representation of this class object. */ public String toString() { ! return (isValue() ? "value " : "") ! + (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) + getName(); } /** * Returns a string describing this {@code Class}, including
*** 248,257 **** --- 248,261 ---- } if (isAnnotation()) { sb.append('@'); } + if (isValue()) { + sb.append("value"); + sb.append(' '); + } if (isInterface()) { // Note: all annotation types are interfaces sb.append("interface"); } else { if (isEnum()) sb.append("enum");
*** 336,345 **** --- 340,353 ---- * types or void. * * <p> If {@code name} denotes an array class, the component type of * the array class is loaded but not initialized. * + * <p> If {@code name} denotes a value class, this method returns + * the {@code Class} object representing the + * {@linkplain #asBoxType() box value type}. + * * <p> For example, in an instance method the expression: * * <blockquote> * {@code Class.forName("Foo")} * </blockquote>
*** 416,425 **** --- 424,437 ---- * * <p> If the class loader of the given module defines other modules and * the given name is a class defined in a different module, this method * returns {@code null} after the class is loaded. </p> * + * <p> If {@code name} denotes a value class, this method returns + * the {@code Class} object representing the + * {@linkplain #asBoxType() box value type}. </p> + * * <p> This method does not check whether the requested class is * accessible to its caller. </p> * * @apiNote * This method returns {@code null} on failure rather than
*** 497,506 **** --- 509,563 ---- } return false; } /** + * Returns a {@code Class} object representing the <em>box type</em> + * of this class if this class is a {@linkplain #isValue() value class}; + * otherwise, returns this class. + * + * <p> A value class has two {@code Class} representations, + * a null-free type or a nullable box type, that can be obtained + * by calling {@link #asValueType()} or {@link #asBoxType()} method + * for conversion. + * + * @return the box type of this class if this class is a value class; + * otherwise, this class. + */ + public Class<?> asBoxType() { + return isValue() ? boxType : this; + } + + /** + * Returns a {@code Class} object representing the <em>null-free value type</em> + * of this class if this class is a {@linkplain #isValue() value class}; + * otherwise, returns {@code null}. + * + * <p> A value class has two {@code Class} representations, + * a null-free type or a nullable box type, that can be obtained + * by calling {@link #asValueType()} or {@link #asBoxType()} method + * for conversion. + * + * @return the unbox value type of this class if this class is a value class; + * otherwise, {@code null}. + */ + public Class<?> asValueType() { + return isValue() ? valueType : null; + } + + /* + * Returns true if this class is a non-value class or a box value class. + */ + boolean isBoxType() { + return boxType == null || this == boxType; + } + + // set by VM if this class is a value type + private transient Class<?> boxType; + private transient Class<?> valueType; + + /** * Creates a new instance of the class represented by this {@code Class} * object. The class is instantiated as if by a {@code new} * expression with an empty argument list. The class is initialized if it * has not already been initialized. *
*** 786,795 **** --- 843,854 ---- * <tr><th scope="row"> boolean <td style="text-align:center"> Z * <tr><th scope="row"> byte <td style="text-align:center"> B * <tr><th scope="row"> char <td style="text-align:center"> C * <tr><th scope="row"> class or interface * <td style="text-align:center"> L<i>classname</i>; + * <tr><th scope="row"> {@linkplain #asValueType() regular value class} + * <td style="text-align:center"> Q<i>classname</i>; * <tr><th scope="row"> double <td style="text-align:center"> D * <tr><th scope="row"> float <td style="text-align:center"> F * <tr><th scope="row"> int <td style="text-align:center"> I * <tr><th scope="row"> long <td style="text-align:center"> J * <tr><th scope="row"> short <td style="text-align:center"> S
*** 803,825 **** * <blockquote><pre> * String.class.getName() * returns "java.lang.String" * byte.class.getName() * returns "byte" * (new Object[3]).getClass().getName() * returns "[Ljava.lang.Object;" * (new int[3][4][5][6][7][8][9]).getClass().getName() * returns "[[[[[[[I" * </pre></blockquote> * * @return the name of the class or interface * represented by this object. */ public String getName() { String name = this.name; ! if (name == null) this.name = name = getName0(); return name; } // cache the name to reduce the number of calls into the VM private transient String name; --- 862,889 ---- * <blockquote><pre> * String.class.getName() * returns "java.lang.String" * byte.class.getName() * returns "byte" + * Point.class.getName() + * returns "p.Point" * (new Object[3]).getClass().getName() * returns "[Ljava.lang.Object;" + * (new Point[3]).getClass().getName() + * returns "[QPoint;" * (new int[3][4][5][6][7][8][9]).getClass().getName() * returns "[[[[[[[I" * </pre></blockquote> * * @return the name of the class or interface * represented by this object. */ public String getName() { String name = this.name; ! if (name == null) { this.name = name = getName0(); + } return name; } // cache the name to reduce the number of calls into the VM private transient String name;
*** 1215,1240 **** * @since 1.1 */ @HotSpotIntrinsicCandidate public native int getModifiers(); - /** * Gets the signers of this class. * * @return the signers of this class, or null if there are no signers. In * particular, this method returns null if this object represents * a primitive type or void. * @since 1.1 */ ! public native Object[] getSigners(); /** * Set the signers of this class. */ ! native void setSigners(Object[] signers); /** * If this {@code Class} object represents a local or anonymous * class within a method, returns a {@link --- 1279,1312 ---- * @since 1.1 */ @HotSpotIntrinsicCandidate public native int getModifiers(); /** * Gets the signers of this class. * * @return the signers of this class, or null if there are no signers. In * particular, this method returns null if this object represents * a primitive type or void. * @since 1.1 */ ! public Object[] getSigners() { ! Class<?> c = (isValue() && !isBoxType()) ? asBoxType() : this; ! return c.getSigners0(); ! } + private native Object[] getSigners0(); /** * Set the signers of this class. */ ! void setSigners(Object[] signers) { ! Class<?> c = (isValue() && !isBoxType()) ? asBoxType() : this; ! c.setSigners0(signers); ! } ! ! native void setSigners0(Object[] signers); /** * If this {@code Class} object represents a local or anonymous * class within a method, returns a {@link
*** 1568,1577 **** --- 1640,1652 ---- * * <p>The simple name of an array is the simple name of the * component type with "[]" appended. In particular the simple * name of an array whose component type is anonymous is "[]". * + * <p>The simple name of a value type is the simple name of + * this class with {@code ".box"} appended. + * * @return the simple name of the underlying class * @since 1.5 */ public String getSimpleName() { ReflectionData<T> rd = reflectionData();
*** 1589,1599 **** String simpleName = getSimpleBinaryName(); if (simpleName == null) { // top level class simpleName = getName(); simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1); // strip the package name } ! return simpleName; } /** * Return an informative string for the name of this type. * --- 1664,1674 ---- String simpleName = getSimpleBinaryName(); if (simpleName == null) { // top level class simpleName = getName(); simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1); // strip the package name } ! return isValue() && isBoxType() ? simpleName + ".box" : simpleName; } /** * Return an informative string for the name of this type. *
*** 1608,1625 **** do { dimensions++; cl = cl.getComponentType(); } while (cl.isArray()); StringBuilder sb = new StringBuilder(); ! sb.append(cl.getName()); for (int i = 0; i < dimensions; i++) { sb.append("[]"); } return sb.toString(); } catch (Throwable e) { /*FALLTHRU*/ } } ! return getName(); } /** * Returns the canonical name of the underlying class as * defined by the Java Language Specification. Returns null if --- 1683,1701 ---- do { dimensions++; cl = cl.getComponentType(); } while (cl.isArray()); StringBuilder sb = new StringBuilder(); ! sb.append(cl.getTypeName()); for (int i = 0; i < dimensions; i++) { sb.append("[]"); } return sb.toString(); } catch (Throwable e) { /*FALLTHRU*/ } } ! // ## append "/box" to box value type instead? ! return isBoxType() ? getName() : getName() + "/val"; } /** * Returns the canonical name of the underlying class as * defined by the Java Language Specification. Returns null if
*** 3619,3635 **** * * @param obj the object to be cast * @return the object after casting, or null if obj is null * * @throws ClassCastException if the object is not ! * null and is not assignable to the type T. * * @since 1.5 */ @SuppressWarnings("unchecked") @HotSpotIntrinsicCandidate public T cast(Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj; } --- 3695,3716 ---- * * @param obj the object to be cast * @return the object after casting, or null if obj is null * * @throws ClassCastException if the object is not ! * {@code null} and is not assignable to the type T. ! * @throws NullPointerException if this class is a {@linkplain #asValueType() ! * null-free value class} and the object is {@code null} * * @since 1.5 */ @SuppressWarnings("unchecked") @HotSpotIntrinsicCandidate public T cast(Object obj) { + if (isValue() && !isBoxType() && obj == null) + throw new NullPointerException(getName() + " is non-nullable value class"); + if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj; }
< prev index next >