8060077: Class.toGenericString specification doesn't mention array types
authordarcy
Fri, 16 Jan 2015 14:04:27 -0800
changeset 28519 299787d4cf96
parent 28518 9a6247bbed98
child 28520 178ac8a1fbde
8060077: Class.toGenericString specification doesn't mention array types Reviewed-by: psandoz, jfranck
jdk/src/java.base/share/classes/java/lang/Class.java
jdk/test/java/lang/Class/GenericStringTest.java
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Fri Jan 16 13:46:39 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Fri Jan 16 14:04:27 2015 -0800
@@ -149,7 +149,8 @@
      * {@code getName}.  If this {@code Class} object represents a
      * primitive type, this method returns the name of the primitive type.  If
      * this {@code Class} object represents void this method returns
-     * "void".
+     * "void". If this {@code Class} object represents an array type,
+     * this method returns "class " followed by {@code getName}.
      *
      * @return a string representation of this class object.
      */
@@ -174,6 +175,12 @@
      * occur in canonical order. If there are no type parameters, the
      * type parameter list is elided.
      *
+     * For an array type, the string starts with the type name,
+     * followed by an angle-bracketed comma-separated list of the
+     * type's type parameters, if any, followed by a sequence of
+     * {@code []} characters, one set of brackets per dimension of
+     * the array.
+     *
      * <p>Note that since information about the runtime representation
      * of a type is being generated, modifiers not present on the
      * originating source code or illegal on the originating source
@@ -189,29 +196,39 @@
             return toString();
         } else {
             StringBuilder sb = new StringBuilder();
-
-            // Class modifiers are a superset of interface modifiers
-            int modifiers = getModifiers() & Modifier.classModifiers();
-            if (modifiers != 0) {
-                sb.append(Modifier.toString(modifiers));
+            Class<?> component = this;
+            int arrayDepth = 0;
+
+            if (isArray()) {
+                do {
+                    arrayDepth++;
+                    component = component.getComponentType();
+                } while (component.isArray());
+                sb.append(component.getName());
+            } else {
+                // Class modifiers are a superset of interface modifiers
+                int modifiers = getModifiers() & Modifier.classModifiers();
+                if (modifiers != 0) {
+                    sb.append(Modifier.toString(modifiers));
+                    sb.append(' ');
+                }
+
+                if (isAnnotation()) {
+                    sb.append('@');
+                }
+                if (isInterface()) { // Note: all annotation types are interfaces
+                    sb.append("interface");
+                } else {
+                    if (isEnum())
+                        sb.append("enum");
+                    else
+                        sb.append("class");
+                }
                 sb.append(' ');
-            }
-
-            if (isAnnotation()) {
-                sb.append('@');
+                sb.append(getName());
             }
-            if (isInterface()) { // Note: all annotation types are interfaces
-                sb.append("interface");
-            } else {
-                if (isEnum())
-                    sb.append("enum");
-                else
-                    sb.append("class");
-            }
-            sb.append(' ');
-            sb.append(getName());
-
-            TypeVariable<?>[] typeparms = getTypeParameters();
+
+            TypeVariable<?>[] typeparms = component.getTypeParameters();
             if (typeparms.length > 0) {
                 boolean first = true;
                 sb.append('<');
@@ -224,6 +241,9 @@
                 sb.append('>');
             }
 
+            for (int i = 0; i < arrayDepth; i++)
+                sb.append("[]");
+
             return sb.toString();
         }
     }
--- a/jdk/test/java/lang/Class/GenericStringTest.java	Fri Jan 16 13:46:39 2015 -0800
+++ b/jdk/test/java/lang/Class/GenericStringTest.java	Fri Jan 16 14:04:27 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,10 +34,29 @@
 
 @ExpectedGenericString("public class GenericStringTest")
 public class GenericStringTest {
-    public static void main(String... args){
+    public Map<String, Integer>[] mixed = null;
+    public Map<String, Integer>[][] mixed2 = null;
+
+    public static void main(String... args) throws ReflectiveOperationException {
         int failures = 0;
 
+        String[][] nested = {{""}};
+        int[][]    intArray = {{1}};
+
         failures += checkToGenericString(int.class, "int");
+        failures += checkToGenericString(void.class, "void");
+        failures += checkToGenericString(args.getClass(), "java.lang.String[]");
+        failures += checkToGenericString(nested.getClass(), "java.lang.String[][]");
+        failures += checkToGenericString(intArray.getClass(), "int[][]");
+        failures += checkToGenericString(java.util.Map.class, "public abstract interface java.util.Map<K,V>");
+
+        Field f = GenericStringTest.class.getDeclaredField("mixed");
+        // The expected value includes "<K,V>" rather than
+        // "<...String,...Integer>" since the Class object rather than
+        // Type objects is being queried.
+        failures += checkToGenericString(f.getType(), "java.util.Map<K,V>[]");
+        f = GenericStringTest.class.getDeclaredField("mixed2");
+        failures += checkToGenericString(f.getType(), "java.util.Map<K,V>[][]");
 
         Class<?>[] types = {
             GenericStringTest.class,