8161500: Use getTypeName and StringJoiner in core reflection toString methods
authordarcy
Mon, 18 Jul 2016 10:27:58 -0700
changeset 39731 7a4bc90065bd
parent 39730 196f4e25d9f5
child 39732 8db47f51465e
8161500: Use getTypeName and StringJoiner in core reflection toString methods Reviewed-by: redestad
jdk/src/java.base/share/classes/java/lang/Class.java
jdk/src/java.base/share/classes/java/lang/reflect/Executable.java
jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java
jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java
jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java
jdk/test/java/lang/Class/GenericStringTest.java
jdk/test/java/lang/reflect/Constructor/GenericStringTest.java
jdk/test/java/lang/reflect/Field/GenericStringTest.java
jdk/test/java/lang/reflect/Method/GenericStringTest.java
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Mon Jul 18 10:27:58 2016 -0700
@@ -238,15 +238,11 @@
 
             TypeVariable<?>[] typeparms = component.getTypeParameters();
             if (typeparms.length > 0) {
-                boolean first = true;
-                sb.append('<');
+                StringJoiner sj = new StringJoiner(",", "<", ">");
                 for(TypeVariable<?> typeparm: typeparms) {
-                    if (!first)
-                        sb.append(',');
-                    sb.append(typeparm.getTypeName());
-                    first = false;
+                    sj.add(typeparm.getTypeName());
                 }
-                sb.append('>');
+                sb.append(sj.toString());
             }
 
             for (int i = 0; i < arrayDepth; i++)
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -28,6 +28,7 @@
 import java.lang.annotation.*;
 import java.util.Map;
 import java.util.Objects;
+import java.util.StringJoiner;
 
 import jdk.internal.misc.SharedSecrets;
 import sun.reflect.annotation.AnnotationParser;
@@ -86,15 +87,6 @@
                getDeclaringClass());
     }
 
-    void separateWithCommas(Class<?>[] types, StringBuilder sb) {
-        for (int j = 0; j < types.length; j++) {
-            sb.append(types[j].getTypeName());
-            if (j < (types.length - 1))
-                sb.append(",");
-        }
-
-    }
-
     void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) {
         int mod = getModifiers() & mask;
 
@@ -121,13 +113,20 @@
 
             printModifiersIfNonzero(sb, modifierMask, isDefault);
             specificToStringHeader(sb);
-
             sb.append('(');
-            separateWithCommas(parameterTypes, sb);
+            StringJoiner sj = new StringJoiner(",");
+            for (Class<?> parameterType : parameterTypes) {
+                sj.add(parameterType.getTypeName());
+            }
+            sb.append(sj.toString());
             sb.append(')');
+
             if (exceptionTypes.length > 0) {
-                sb.append(" throws ");
-                separateWithCommas(exceptionTypes, sb);
+                StringJoiner joiner = new StringJoiner(",", "throws ", "");
+                for (Class<?> exceptionType : exceptionTypes) {
+                    joiner.add(exceptionType.getTypeName());
+                }
+                sb.append(joiner.toString());
             }
             return sb.toString();
         } catch (Exception e) {
@@ -149,42 +148,34 @@
 
             TypeVariable<?>[] typeparms = getTypeParameters();
             if (typeparms.length > 0) {
-                boolean first = true;
-                sb.append('<');
+                StringJoiner sj = new StringJoiner(",", "<", "> ");
                 for(TypeVariable<?> typeparm: typeparms) {
-                    if (!first)
-                        sb.append(',');
-                    // Class objects can't occur here; no need to test
-                    // and call Class.getName().
-                    sb.append(typeparm.toString());
-                    first = false;
+                    sj.add(typeparm.getTypeName());
                 }
-                sb.append("> ");
+                sb.append(sj.toString());
             }
 
             specificToGenericStringHeader(sb);
 
             sb.append('(');
+            StringJoiner sj = new StringJoiner(",");
             Type[] params = getGenericParameterTypes();
             for (int j = 0; j < params.length; j++) {
                 String param = params[j].getTypeName();
                 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
                     param = param.replaceFirst("\\[\\]$", "...");
-                sb.append(param);
-                if (j < (params.length - 1))
-                    sb.append(',');
+                sj.add(param);
             }
+            sb.append(sj.toString());
             sb.append(')');
-            Type[] exceptions = getGenericExceptionTypes();
-            if (exceptions.length > 0) {
-                sb.append(" throws ");
-                for (int k = 0; k < exceptions.length; k++) {
-                    sb.append((exceptions[k] instanceof Class)?
-                              ((Class)exceptions[k]).getName():
-                              exceptions[k].toString());
-                    if (k < (exceptions.length - 1))
-                        sb.append(',');
+
+            Type[] exceptionTypes = getGenericExceptionTypes();
+            if (exceptionTypes.length > 0) {
+                StringJoiner joiner = new StringJoiner(",", " throws ", "");
+                for (Type exceptionType : exceptionTypes) {
+                    joiner.add(exceptionType.getTypeName());
                 }
+                sb.append(joiner.toString());
             }
             return sb.toString();
         } catch (Exception e) {
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/GenericArrayTypeImpl.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -65,15 +65,7 @@
     }
 
     public String toString() {
-        Type componentType = getGenericComponentType();
-        StringBuilder sb = new StringBuilder();
-
-        if (componentType instanceof Class)
-            sb.append(((Class)componentType).getName() );
-        else
-            sb.append(componentType.toString());
-        sb.append("[]");
-        return sb.toString();
+        return getGenericComponentType().getTypeName() + "[]";
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/ParameterizedTypeImpl.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -33,6 +33,7 @@
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 import java.util.Arrays;
+import java.util.StringJoiner;
 import java.util.Objects;
 
 /** Implementing class for ParameterizedType interface. */
@@ -207,10 +208,7 @@
         StringBuilder sb = new StringBuilder();
 
         if (ownerType != null) {
-            if (ownerType instanceof Class)
-                sb.append(((Class)ownerType).getName());
-            else
-                sb.append(ownerType.toString());
+            sb.append(ownerType.getTypeName());
 
             sb.append(".");
 
@@ -224,17 +222,13 @@
         } else
             sb.append(rawType.getName());
 
-        if (actualTypeArguments != null &&
-            actualTypeArguments.length > 0) {
-            sb.append("<");
-            boolean first = true;
+        if (actualTypeArguments != null) {
+            StringJoiner sj = new StringJoiner(", ", "<", ">");
+            sj.setEmptyValue("");
             for(Type t: actualTypeArguments) {
-                if (!first)
-                    sb.append(", ");
-                sb.append(t.getTypeName());
-                first = false;
+                sj.add(t.getTypeName());
             }
-            sb.append(">");
+            sb.append(sj.toString());
         }
 
         return sb.toString();
--- a/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/WildcardTypeImpl.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -32,6 +32,7 @@
 import sun.reflect.generics.tree.FieldTypeSignature;
 import sun.reflect.generics.visitor.Reifier;
 import java.util.Arrays;
+import java.util.StringJoiner;
 
 
 /**
@@ -156,14 +157,12 @@
 
         assert bounds.length > 0;
 
-        boolean first = true;
+        StringJoiner sj = new StringJoiner(" & ");
         for(Type bound: bounds) {
-            if (!first)
-                sb.append(" & ");
+            sj.add(bound.getTypeName());
+        }
+        sb.append(sj.toString());
 
-            first = false;
-            sb.append(bound.getTypeName());
-        }
         return sb.toString();
     }
 
--- a/jdk/test/java/lang/Class/GenericStringTest.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/test/java/lang/Class/GenericStringTest.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 6298888 6992705
+ * @bug 6298888 6992705 8161500
  * @summary Check Class.toGenericString()
  * @author Joseph D. Darcy
  */
@@ -58,15 +58,11 @@
         f = GenericStringTest.class.getDeclaredField("mixed2");
         failures += checkToGenericString(f.getType(), "java.util.Map<K,V>[][]");
 
-        Class<?>[] types = {
-            GenericStringTest.class,
-            AnInterface.class,
-            LocalMap.class,
-            AnEnum.class,
-            AnotherEnum.class,
-        };
-
-        for(Class<?> clazz : types) {
+        for(Class<?> clazz : List.of(GenericStringTest.class,
+                                     AnInterface.class,
+                                     LocalMap.class,
+                                     AnEnum.class,
+                                     AnotherEnum.class)) {
             failures += checkToGenericString(clazz, clazz.getAnnotation(ExpectedGenericString.class).value());
         }
 
--- a/jdk/test/java/lang/reflect/Constructor/GenericStringTest.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/test/java/lang/reflect/Constructor/GenericStringTest.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5033583 6316717 6470106
+ * @bug 5033583 6316717 6470106 8161500
  * @summary Check toGenericString() and toString() methods
  * @author Joseph D. Darcy
  */
@@ -35,12 +35,8 @@
 public class GenericStringTest {
     public static void main(String argv[]) throws Exception{
         int failures = 0;
-        List<Class<?>> classList = new LinkedList<Class<?>>();
-        classList.add(TestClass1.class);
-        classList.add(TestClass2.class);
 
-
-        for(Class<?> clazz: classList)
+        for(Class<?> clazz: List.of(TestClass1.class, TestClass2.class))
             for(Constructor<?> ctor: clazz.getDeclaredConstructors()) {
                 ExpectedGenericString egs = ctor.getAnnotation(ExpectedGenericString.class);
                 String actual = ctor.toGenericString();
--- a/jdk/test/java/lang/reflect/Field/GenericStringTest.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/test/java/lang/reflect/Field/GenericStringTest.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5033583
+ * @bug 5033583 8161500
  * @summary Check toGenericString() method
  * @author Joseph D. Darcy
  */
@@ -35,12 +35,8 @@
 public class GenericStringTest {
     public static void main(String argv[]) throws Exception {
         int failures = 0;
-        List<Class> classList = new LinkedList<Class>();
-        classList.add(TestClass1.class);
-        classList.add(TestClass2.class);
 
-
-        for(Class clazz: classList)
+        for(Class clazz: List.of(TestClass1.class, TestClass2.class))
             for(Field field: clazz.getDeclaredFields()) {
                 ExpectedString es = field.getAnnotation(ExpectedString.class);
                 String genericString = field.toGenericString();
@@ -61,15 +57,15 @@
 
 class TestClass1 {
     @ExpectedString("int TestClass1.field1")
-        int field1;
+    int field1;
 
     @ExpectedString("private static java.lang.String TestClass1.field2")
-        private static String field2;
+    private static String field2;
 }
 
 class TestClass2<E> {
     @ExpectedString("public E TestClass2.field1")
-        public E field1;
+    public E field1;
 }
 
 @Retention(RetentionPolicy.RUNTIME)
--- a/jdk/test/java/lang/reflect/Method/GenericStringTest.java	Mon Jul 18 15:34:22 2016 +0100
+++ b/jdk/test/java/lang/reflect/Method/GenericStringTest.java	Mon Jul 18 10:27:58 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 5033583 6316717 6470106 8004979
+ * @bug 5033583 6316717 6470106 8004979 8161500
  * @summary Check toGenericString() and toString() methods
  * @author Joseph D. Darcy
  */
@@ -35,14 +35,9 @@
 public class GenericStringTest {
     public static void main(String argv[]) throws Exception {
         int failures = 0;
-        List<Class<?>> classList = new LinkedList<Class<?>>();
-        classList.add(TestClass1.class);
-        classList.add(TestClass2.class);
-        classList.add(Roebling.class);
-        classList.add(TestInterface1.class);
 
-
-        for(Class<?> clazz: classList)
+        for(Class<?> clazz: List.of(TestClass1.class, TestClass2.class,
+                                    Roebling.class, TestInterface1.class))
             for(Method method: clazz.getDeclaredMethods()) {
                 ExpectedGenericString egs = method.getAnnotation(ExpectedGenericString.class);
                 if (egs != null) {
@@ -121,6 +116,30 @@
     @ExpectedGenericString(
    "public void TestClass2.method2() throws F")
     public void method2() throws F {return;}
+
+    @ExpectedGenericString(
+   "public E[] TestClass2.method3()")
+    public E[] method3() {return null;}
+
+    @ExpectedGenericString(
+   "public E[][] TestClass2.method4()")
+    public E[][] method4() {return null;}
+
+    @ExpectedGenericString(
+   "public java.util.List<E[]> TestClass2.method5()")
+    public List<E[]> method5() {return null;}
+
+    @ExpectedGenericString(
+   "public java.util.List<?> TestClass2.method6()")
+    public List<?> method6() {return null;}
+
+    @ExpectedGenericString(
+   "public java.util.List<?>[] TestClass2.method7()")
+    public List<?>[] method7() {return null;}
+
+    @ExpectedGenericString(
+   "public <K,V> java.util.Map<K, V> TestClass2.method8()")
+    public <K, V> Map<K, V> method8() {return null;}
 }
 
 class Roebling implements Comparable<Roebling> {
@@ -157,7 +176,6 @@
     @ExpectedGenericString(
     "public default strictfp double TestInterface1.quux()")
     strictfp default double quux(){return 1.0;}
-
 }
 
 @Retention(RetentionPolicy.RUNTIME)