JDK-8062794 : TypeVariable.getAnnotatedBounds is incompatible to earlier version
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 8u25,8u40
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-10-24
  • Updated: 2014-11-06
  • Resolved: 2014-11-05
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
I wanted to update a third-party class that implement interface java.lang.reflect.TypeVariable<D> so that I can compile it both with Java SE 7 and 8, but new method getAnnotatedBounds made it impossible.

The new method must return an array of java.lang.reflect.AnnotatedType that was introduced in Java SE 8 but I must implement getAnnotatedBounds so that I can compile the class with Java SE 8 but without AnnotatedType to compile it with Java SE 7.  The addition of getAnnotatedBounds prevents me from choosing Java SE 7 or 8 when compiling the class source code.

I hope you know how to cope with such incompatibility.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Make Demo.java with the following content:

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class Demo implements TypeVariable<Class> {
    public Type[] getBounds() {
        throw new UnsupportedOperationException();
    }
    public Class getGenericDeclaration() {
        throw new UnsupportedOperationException();
    }
    public String getName() {
        throw new UnsupportedOperationException();
    }
    public java.lang.reflect.AnnotatedType[] getAnnotatedBounds() {
        throw new UnsupportedOperationException();
    }
    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
        throw new UnsupportedOperationException();
    }
    public Annotation[] getAnnotations() {
        throw new UnsupportedOperationException();
    }
    public Annotation[] getDeclaredAnnotations() {
        throw new UnsupportedOperationException();
    }
}

2. Compile Demo.java with Java SE 8 javac.
3. Compile Demo.java with Java SE 7 javac.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The class is compiled without errors on both versions.
ACTUAL -
It is successfully compiled with Java SE 8 but not with Java SE 7.  If I remove method getAnnotatedBounds and import java.lang.reflect.AnnotatedType, it is successfully compiled with Java SE 7 but not with Java SE 8.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Java SE 7 javac with getAnnotatedBounds:

Demo.java:16: error: cannot find symbol
    public java.lang.reflect.AnnotatedType[] getAnnotatedBounds() {
                            ^
  symbol:   class AnnotatedType
  location: package java.lang.reflect
1 error

Java SE 8 javac without get AnnotatedBounds:

Demo.java:6: error: Demo is not abstract and does not override abstract method getAnnotatedBounds() in TypeVariable
public class Demo implements TypeVariable<Class> {
       ^
1 error

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
No need to execute the program.
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Write my own version of interface TypeVariable<D> like the Java SE 7 definition.  I do not know if other classes would use the real TypeVariable<D>.


Comments
The API changes done under JDK-8004698 added a method to the existing TypeVariable interface. In retrospect, it would have been more source compatible to make getAnnotatedBounds method a default method. However, having implementations of TypeVariable outside of the JDK should be fairly rare. In any case, to have a single source file that will compile under either JDK 7 or JDK 8, an annotation processor can be used to generate the superclass of the TypeVariable implementation, including a getAnnotatedBounds method when compiling on JDK 8 and not including such a method otherwise. For some guidance on using annotation processors in this way see: https://blogs.oracle.com/darcy/entry/properties_via_annotation_processing Also, JavaOne 2014 included several talk on annotation processing. Closing as will not fix.
05-11-2014

The API changes done under JDK-8004698 added a method to the existing TypeVariable interface. In retrospect, it would have been more source compatible to make getAnnotatedBounds method a default method. However, having implementations of TypeVariable outside of the JDK should be fairly rare. In any case, to have a single source file that will compile under either JDK 7 or JDK 8, an annotation processor can be used to generate the superclass of the TypeVariable implementation, including a getAnnotatedBounds method when compiling on JDK 8 and not including such a method otherwise. For some guidance on using annotation processors in this way see: https://blogs.oracle.com/darcy/entry/properties_via_annotation_processing Also, JavaOne 2014 included several talk on annotation processing. Closing as will not fix.
05-11-2014

Tested with JDK 7u71, 8u25 and 8u40 and the compiler behaves as reported in the issue.
04-11-2014