changeset 12169:b91b65ccf504

8054304: Clarify treatment of bounds in j.l.r.Annotated{WildcardType,TypeVariable}. Summary: Reflection APIs should return unannotated Object as the upper bound when there is no explicit upper bound. Reviewed-by: darcy
author sadayapalam
date Fri, 12 Jun 2015 10:58:31 +0530
parents 551323004d0c
children 5f9b3c9dda45
files src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java src/java.base/share/classes/java/lang/reflect/TypeVariable.java src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java test/java/lang/annotation/TypeAnnotationReflection.java
diffstat 5 files changed, 75 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java	Fri Jun 12 10:58:31 2015 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -36,6 +36,8 @@
 
     /**
      * Returns the potentially annotated bounds of this type variable.
+     * Note that if no bound is explicitly declared, the bound is unannotated
+     * {@code Object}.
      *
      * @return the potentially annotated bounds of this type variable
      */
--- a/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java	Fri Jun 12 10:58:31 2015 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -36,13 +36,18 @@
 
     /**
      * Returns the potentially annotated lower bounds of this wildcard type.
+     * Note that if no lower bound is explicitly declared, the lower bound is the
+     * type of null. In this case, a zero length array is returned.
      *
-     * @return the potentially annotated lower bounds of this wildcard type
+     * @return the potentially annotated lower bounds of this wildcard type or
+     * an empty array if no lower bound is explicitly declared.
      */
     AnnotatedType[] getAnnotatedLowerBounds();
 
     /**
      * Returns the potentially annotated upper bounds of this wildcard type.
+     * Note that if no upper bound is explicitly declared, the upper bound is
+     * unannotated {@code Object}
      *
      * @return the potentially annotated upper bounds of this wildcard type
      */
--- a/src/java.base/share/classes/java/lang/reflect/TypeVariable.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/TypeVariable.java	Fri Jun 12 10:58:31 2015 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -91,11 +91,11 @@
      * Returns an array of AnnotatedType objects that represent the use of
      * types to denote the upper bounds of the type parameter represented by
      * this TypeVariable. The order of the objects in the array corresponds to
-     * the order of the bounds in the declaration of the type parameter.
+     * the order of the bounds in the declaration of the type parameter. Note that
+     * if no upper bound is explicitly declared, the upper bound is unannotated
+     * {@code Object}.
      *
-     * Returns an array of length 0 if the type parameter declares no bounds.
-     *
-     * @return an array of objects representing the upper bounds of the type variable
+     * @return an array of objects representing the upper bound(s) of the type variable
      * @since 1.8
      */
      AnnotatedType[] getAnnotatedBounds();
--- a/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java	Fri Jun 12 10:58:31 2015 +0530
@@ -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
@@ -277,8 +277,14 @@
 
         @Override
         public AnnotatedType[] getAnnotatedUpperBounds() {
-            if (!hasUpperBounds())
-                return new AnnotatedType[0];
+            if (!hasUpperBounds()) {
+                return new AnnotatedType[] { buildAnnotatedType(Object.class,
+                                                                LocationInfo.BASE_LOCATION,
+                                                                new TypeAnnotation[0],
+                                                                new TypeAnnotation[0],
+                                                                null)
+                                           };
+            }
             return getAnnotatedBounds(getWildcardType().getUpperBounds());
         }
 
--- a/test/java/lang/annotation/TypeAnnotationReflection.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/test/java/lang/annotation/TypeAnnotationReflection.java	Fri Jun 12 10:58:31 2015 +0530
@@ -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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8004698 8007073 8022343
+ * @bug 8004698 8007073 8022343 8054304 8058595
  * @summary Unit test for type annotations
  */
 
@@ -200,6 +200,17 @@
         check(annos.length == 1);
         check(annos[0].annotationType().equals(TypeAnno.class));
         check(((TypeAnno)annos[0]).value().equals("M Runnable"));
+
+        // Check that AnnotatedTypeVariable.getAnnotatedBounds() returns jlO for a naked
+        // type variable (i.e no bounds, no annotations)
+        Method m4 = TestClassTypeVarAndField.class.getDeclaredMethod("foo4", (Class<?>[])null);
+        AnnotatedType ret4 = m4.getAnnotatedReturnType();
+        AnnotatedType[] annotatedBounds4 = ((AnnotatedTypeVariable)ret4).getAnnotatedBounds();
+        check(annotatedBounds4.length == 1);
+
+        annos = annotatedBounds4[0].getAnnotations();
+        check(annos.length == 0);
+        check(annotatedBounds4[0].getType().equals(Object.class));
     }
 
     private static void testFields() throws Exception {
@@ -231,7 +242,7 @@
     private static void testClassTypeVar() throws Exception {
         TypeVariable[] typeVars = TestClassTypeVarAndField.class.getTypeParameters();
         Annotation[] annos;
-        check(typeVars.length == 2);
+        check(typeVars.length == 3);
 
         // First TypeVar
         AnnotatedType[] annotatedBounds = typeVars[0].getAnnotatedBounds();
@@ -262,6 +273,14 @@
         check(annos.length == 1);
         check(annos[0].annotationType().equals(TypeAnno2.class));
         check(((TypeAnno2)annos[0]).value().equals("EEBound"));
+
+        // third Typevar V declared without explicit bounds should see jlO as its bound.
+        annotatedBounds = typeVars[2].getAnnotatedBounds();
+        check(annotatedBounds.length == 1);
+
+        annos = annotatedBounds[0].getAnnotations();
+        check(annos.length == 0);
+        check(annotatedBounds[0].getType().equals(Object.class));
     }
 
     private static void testMethodTypeVar() throws Exception {
@@ -282,7 +301,7 @@
         // Second method
         m2 = TestClassTypeVarAndField.class.getDeclaredMethod("foo3", (Class<?>[])null);
         t = m2.getTypeParameters();
-        check(t.length == 1);
+        check(t.length == 2);
         annos = t[0].getAnnotations();
         check(annos.length == 1);
         check(annos[0].annotationType().equals(TypeAnno.class));
@@ -293,6 +312,14 @@
 
         annos = annotatedBounds2[0].getAnnotations();
         check(annos.length == 0);
+
+        // for the naked type variable L of foo3, we should see jlO as its bound.
+        annotatedBounds2 = t[1].getAnnotatedBounds();
+        check(annotatedBounds2.length == 1);
+        check(annotatedBounds2[0].getType().equals(Object.class));
+
+        annos = annotatedBounds2[0].getAnnotations();
+        check(annos.length == 0);
     }
 
     private static void testParameterizedType() {
@@ -357,9 +384,24 @@
         w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
             .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
         t = w.getAnnotatedUpperBounds();
-        check(t.length == 0);
+        check(t.length == 1);
+        check(t[0].getType().equals(Object.class));
+        annos = t[0].getAnnotations();
+        check(annos.length == 0);
         t = w.getAnnotatedLowerBounds();
         check(t.length == 1);
+
+        // for an unbounded wildcard, we should see jlO as its upperbound and null type as its lower bound.
+        f = TestWildcardType.class.getDeclaredField("f3");
+        w = (AnnotatedWildcardType)((AnnotatedParameterizedType)f
+            .getAnnotatedType()).getAnnotatedActualTypeArguments()[0];
+        t = w.getAnnotatedUpperBounds();
+        check(t.length == 1);
+        check(t[0].getType().equals(Object.class));
+        annos = t[0].getAnnotations();
+        check(annos.length == 0);
+        t = w.getAnnotatedLowerBounds();
+        check(t.length == 0);
     }
 
     private static void testParameterTypes() throws Exception {
@@ -515,6 +557,7 @@
     public <T> List<? super T> foo() { return null;}
     public Class<@TypeAnno("1") ? extends @TypeAnno("2") Annotation> f1;
     public Class<@TypeAnno("3") ? super @TypeAnno("4") Annotation> f2;
+    public Class<@TypeAnno("5") ?> f3;
 }
 
 abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
@@ -555,14 +598,15 @@
 
 abstract class TestClassTypeVarAndField <T extends @TypeAnno("Object1") Object
                                           & @TypeAnno("Runnable1") @TypeAnno2("Runnable2") Runnable,
-                                        @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable > {
+                                        @TypeAnno("EE")EE extends @TypeAnno2("EEBound") Runnable, V > {
     @TypeAnno("T1 field") @TypeAnno2("T2 field") T field1;
     T field2;
     @TypeAnno("Object field") Object field3;
 
     public @TypeAnno("t1") @TypeAnno2("t2") T foo(){ return null; }
     public <M extends @TypeAnno("M Runnable") Runnable> M foo2() {return null;}
-    public <@TypeAnno("K") K extends Cloneable> K foo3() {return null;}
+    public <@TypeAnno("K") K extends Cloneable, L> K foo3() {return null;}
+    public <L> L foo4() {return null;}
 }
 
 @Target(ElementType.TYPE_USE)