< prev index next >

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

Print this page
rev 55127 : 8223351: [lworld] Primary mirror and nullable mirror for inline type
Reviewed-by: tbd

*** 60,71 **** import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; - import java.util.StringJoiner; - import java.util.stream.Stream; import java.util.stream.Collectors; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; --- 60,69 ----
*** 195,207 **** * this method returns "class " followed by {@code getName}. * * @return a string representation of this class object. */ public String toString() { ! return (isValue() ? "inline " : "") + (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) ! + getName() + (isValue() && isBoxType() ? "?" : ""); } /** * Returns a string describing this {@code Class}, including * information about modifiers and type parameters. --- 193,205 ---- * this method returns "class " followed by {@code getName}. * * @return a string representation of this class object. */ public String toString() { ! return (isInlineClass() ? "inline " : "") + (isInterface() ? "interface " : (isPrimitive() ? "" : "class ")) ! + getName() + (isInlineClass() && isNullableType() ? "?" : ""); } /** * Returns a string describing this {@code Class}, including * information about modifiers and type parameters.
*** 258,268 **** } if (isAnnotation()) { sb.append('@'); } ! if (isValue()) { sb.append("value"); sb.append(' '); } if (isInterface()) { // Note: all annotation types are interfaces sb.append("interface"); --- 256,266 ---- } if (isAnnotation()) { sb.append('@'); } ! if (isInlineClass()) { sb.append("value"); sb.append(' '); } if (isInterface()) { // Note: all annotation types are interfaces sb.append("interface");
*** 360,373 **** * 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> --- 358,367 ----
*** 444,457 **** * * <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 --- 438,447 ----
*** 510,524 **** } } /** ! * Returns {@code true} if this class is a value class. * ! * @return {@code true} if this class is a value class. */ ! public boolean isValue() { int mods = this.getModifiers(); if ((mods & VALUE_TYPE) != 0) { if ((mods & (Modifier.INTERFACE | Modifier.ABSTRACT)) != 0) { throw new InternalError("inline class can't have ACC_INTERFACE or ACC_ABSTRACT set"); } --- 500,514 ---- } } /** ! * Returns {@code true} if this class is an inline class. * ! * @return {@code true} if this class is an inline class. */ ! public boolean isInlineClass() { int mods = this.getModifiers(); if ((mods & VALUE_TYPE) != 0) { if ((mods & (Modifier.INTERFACE | Modifier.ABSTRACT)) != 0) { throw new InternalError("inline class can't have ACC_INTERFACE or ACC_ABSTRACT set"); }
*** 529,583 **** } 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. */ @HotSpotIntrinsicCandidate ! public Class<T> 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}. */ @HotSpotIntrinsicCandidate ! public Class<T> 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<T> boxType; ! private transient Class<T> 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 --- 519,578 ---- } return false; } /** ! * Returns a {@code Class} object representing the <em>nullable-projection</em> ! * type if this class is an {@linkplain #isInlineClass() inline class}; * otherwise, returns this class. * ! * <p> An inline class has two {@code Class} representations, ! * the zero-default inline class and the nullable-projection type ! * that can be obtained by calling {@link #asPrimaryType()} or ! * {@link #asNullableType()} method respectively. * ! * @return the {@code Class} object representing the nullable-projection of ! * this class if this class is an inline class; otherwise, this class. */ @HotSpotIntrinsicCandidate ! public Class<T> asNullableType() { ! return isInlineClass() ? nullableType : this; } /** ! * Returns a {@code Class} object representing this <em>zero-default</em> ! * inline class if this class is an {@linkplain #isInlineClass() inline class}; ! * otherwise, returns this class. * ! * <p> An inline class has two {@code Class} representations, ! * the zero-default inline class and the nullable-projection type ! * that can be obtained by calling {@link #asPrimaryType()} or ! * {@link #asNullableType()} method respectively. * ! * @return the {@code Class} object representing the zero-default inline class ! * if this class is an inline class; otherwise, this class. */ @HotSpotIntrinsicCandidate ! public Class<T> asPrimaryType() { ! return isInlineClass() ? inlineType : this; } ! /** ! * Returns {@code true} if this class is a nullable type. A nullable type ! * can be a reference class or interface and ! * a {@linkplain #asNullableType nullable-projection type}. ! * ! * @return {@code true} if this class is a nullable type. */ ! public boolean isNullableType() { ! return nullableType == null || this == nullableType; } ! // set by VM if this class is an inline type ! // otherwise, these two fields are null ! private transient Class<T> inlineType; ! private transient Class<T> nullableType; /** * 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
*** 633,643 **** @CallerSensitive @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException { ! if (this.isValue()) { throw new IllegalAccessException( "cannot create new instance of an inline class " + this.getName()); } SecurityManager sm = System.getSecurityManager(); --- 628,638 ---- @CallerSensitive @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException { ! if (this.isInlineClass()) { throw new IllegalAccessException( "cannot create new instance of an inline class " + this.getName()); } SecurityManager sm = System.getSecurityManager();
*** 853,863 **** * <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 --- 848,858 ---- * <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 #asPrimaryType() inline 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
*** 873,887 **** * 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 --- 868,884 ---- * String.class.getName() * returns "java.lang.String" * byte.class.getName() * returns "byte" * Point.class.getName() ! * returns "Point" * (new Object[3]).getClass().getName() * returns "[Ljava.lang.Object;" * (new Point[3]).getClass().getName() * returns "[QPoint;" + * (new Point?[3][4]).getClass().getName() + * returns "[[LPoint;" * (new int[3][4][5][6][7][8][9]).getClass().getName() * returns "[[[[[[[I" * </pre></blockquote> * * @return the name of the class or interface
*** 1296,1316 **** * 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); --- 1293,1313 ---- * particular, this method returns null if this object represents * a primitive type or void. * @since 1.1 */ public Object[] getSigners() { ! Class<?> c = isInlineClass() && isNullableType() ? asPrimaryType() : this; return c.getSigners0(); } private native Object[] getSigners0(); /** * Set the signers of this class. */ void setSigners(Object[] signers) { ! Class<?> c = isInlineClass() && isNullableType() ? asPrimaryType() : this; c.setSigners0(signers); } native void setSigners0(Object[] signers);
*** 1648,1660 **** * * <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(); --- 1645,1654 ----
*** 1672,1682 **** 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. * --- 1666,1676 ---- 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. *
*** 1698,1709 **** 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 --- 1692,1702 ---- sb.append("[]"); } return sb.toString(); } catch (Throwable e) { /*FALLTHRU*/ } } ! return toTypeName(); } /** * Returns the canonical name of the underlying class as * defined by the Java Language Specification. Returns null if
*** 3524,3540 **** private String methodToString(String name, Class<?>[] argTypes) { StringBuilder sb = new StringBuilder(); sb.append(getName() + "." + name + "("); if (argTypes != null) { sb.append(Arrays.stream(argTypes) ! .map(c -> (c == null) ? "null" : c.getName()) .collect(Collectors.joining(","))); } sb.append(")"); return sb.toString(); } /** use serialVersionUID from JDK 1.1 for interoperability */ private static final long serialVersionUID = 3206093459760846163L; /** --- 3517,3541 ---- private String methodToString(String name, Class<?>[] argTypes) { StringBuilder sb = new StringBuilder(); sb.append(getName() + "." + name + "("); if (argTypes != null) { sb.append(Arrays.stream(argTypes) ! .map(c -> (c == null) ? "null" : c.toTypeName()) .collect(Collectors.joining(","))); } sb.append(")"); return sb.toString(); } + /* + * Returns the class name appended with "?" if it is the nullable projection + * of an inline class. + */ + private String toTypeName() { + return isInlineClass() && isNullableType() ? getName() + "?" : getName(); + } + /** use serialVersionUID from JDK 1.1 for interoperability */ private static final long serialVersionUID = 3206093459760846163L; /**
*** 3705,3724 **** * @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; } --- 3706,3725 ---- * @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 an {@linkplain #asPrimaryType() ! * inline class} and the object is {@code null} * * @since 1.5 */ @SuppressWarnings("unchecked") @HotSpotIntrinsicCandidate public T cast(Object obj) { ! if (isInlineClass() && !isNullableType() && obj == null) ! throw new NullPointerException(getName() + " is an inline class"); if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj; }
< prev index next >