2015-11-05 8 views
6

Ich habe das gerade heute entdeckt, als einer meiner Komponententests aufgrund eines Upgrades von Java 7 auf Java 8 fehlschlug. Der Komponententest ruft eine Methode auf, die versucht, eine Annotation für eine Methode zu finden, die mit einer anderen Klasse versehen ist Rückgabetyp.Warum funktioniert isAnnotationPresent zwischen Java 7 und Java 8 anders?

In Java 7, isAnnotationPresent scheint nur Anmerkungen zu finden, wenn sie wirklich im Code deklariert wurden. In Java 8 scheint isAnnotationPresent Anmerkungen zu enthalten, die in untergeordneten Klassen deklariert wurden.

Um dies zu veranschaulichen, habe ich eine einfache (??) Testklasse IAPTest (für IsAnnotationPresentTest) erstellt.

Auf der neuesten Java 7 (1.7.0_79 zum Zeitpunkt des Schreibens), diese Methode druckt "falsch". Auf dem neuesten Java 8 (1.8.0_66 zum Zeitpunkt des Schreibens) gibt diese Methode "true" aus. Ich würde intuitiv erwarten, dass es "falsch" druckt.

Warum ist das? Bedeutet dies einen Fehler in Java oder eine beabsichtigte Änderung in der Funktionsweise von Java?

EDIT: Nur die genauen Befehle zu zeigen, habe ich dies zu replizieren (in einem Verzeichnis mit IAPTest.java identisch mit dem Codeblock oben):

C:\test-isannotationpresent>del *.class 

C:\test-isannotationpresent>set JAVA_HOME=C:\nma\Toolsets\AJB1\OracleJDK\jdk1.8.0_66 

C:\test-isannotationpresent>set PATH=%PATH%;C:\nma\Toolsets\AJB1\OracleJDK\jdk1.8.0_66\bin 

C:\test-isannotationpresent>java -version 
java version "1.8.0_66" 
Java(TM) SE Runtime Environment (build 1.8.0_66-b17) 
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode) 

C:\test-isannotationpresent>javac IAPTest.java 

C:\test-isannotationpresent>java IAPTest 
true 

C:\test-isannotationpresent> 
+0

Hmm, das druckt für mich "falsch": Eclipse Mars 4.5.1, JDK 1.8.0_51. – Tunaki

+0

Warum denken Sie, dass Anmerkungen "in Kinderklassen" deklariert wurden? Sie haben die Methode in "B" kommentiert und suchen die * deklarierten Methoden * von 'B' und sonst nichts. Es sind keine Kinderklassen involviert. – Holger

+0

@Holger wenn ich nach den deklarierten Methoden von 'B' suche, finde ich zwei Methoden. Eine Methode repräsentiert die Methode in der Kindklasse und eine Methode repräsentiert die Methode in der Elternklasse. Das können Sie an den Rückgabetypen erkennen. 'B.class.getDeclaredMethods(). Length == 2' sowohl in Java 7 als auch in 8. Da ich den Rückgabetyp überprüfe, um sicherzustellen, dass die Elternklassenmethode die referenzierte ist (Rückgabetyp ist' I' und nicht 'IE'), die Methode in' A' hat keine Annotation, sondern nur die Annotation in der Kindklasse 'B'. – Kidburla

Antwort

10

Ich glaube, dies zu einer Veränderung zusammenhängt in den java 8 compatibility guide

erwähnt

Ab diesem Release, Parameter und Verfahren Anmerkungen zu synthetischer Brücke methods.This kopiert beheben bedeutet, dass jetzt für Programme wie:

Jede generierte Bridge-Methode enthält alle Annotationen der -Methode, an die sie weitergeleitet wird. Parameter Anmerkungen werden ebenfalls kopiert. Diese Änderung des Verhaltens kann sich auf einige Annotationsprozessoren oder auf Anwendungen auswirken, die die Annotationen verwenden.

Die zweite Methode, die ein I anstelle ein IE zurückgibt, ist ein synthetisches Verfahren erzeugt, weil Sie einen engeren Rückgabetyp in der überschriebenen Methode als in der Superklasse haben. Beachten Sie, dass es in der Liste der deklarierten Methoden nicht vorhanden ist, wenn Sie keinen einschränkenden Rückgabetyp haben. Also ich denke, das ist kein Fehler, sondern eine bewusste Veränderung.

+1

Große Antwort! Sie haben mir nicht nur die Argumentation und die Dokumentation geliefert, sondern auch, wie ich meinen Komponententest reparieren kann, um mit Java 8 zu arbeiten - ich muss nur 'isSynthetic' verwenden. Vielen Dank! – Kidburla

Verwandte Themen