Wystąpił problem w języku Java Generics, w którym ten sam kod zostanie skompilowany i będzie działał poprawnie w Javie 6, ale nie uda się go skompilować z powodu tego samego usunięcia w Javie 5. mam TestErasure.java pliku, który ma przeciążone metody o nazwie „metoda”:Odmienne zachowanie między Java 5 i 6 podczas przeciążania ogólnych metod
import java.util.ArrayList;
import java.util.List;
public class TestErasure {
public static Object method(List<Object> list) {
System.out.println("method(List<Object> list)");
return null;
}
public static String method(List<String> list) {
System.out.println("method(List<String> list)");
return null;
}
public static void main(String[] args) {
method(new ArrayList<Object>());
method(new ArrayList<String>());
}
}
W Javie 5, uzyskać oczekiwany błąd kompilacji, stwierdzając, że wymazanie „metoda” jest taka sama:
$ javac -version
javac 1.5.0_19
$ javac TestErasure.java
TestErasure.java:10: name clash: method(java.util.List<java.lang.String>) and method(java.util.List<java.lang.Object>) have the same erasure
public static String method(List<String> list) {
^
TestErasure.java:17: method(java.util.List<java.lang.Object>) in TestErasure cannot be applied to (java.util.ArrayList<java.lang.String>)
method(new ArrayList<String>());
^
2 errors
Jednak Java 6 jest w stanie skompilować i uruchomić ten sam kod.
$ javac -version
javac 1.6.0_16
$ javac TestErasure.java
$ java TestErasure
method(List<Object> list)
method(List<String> list)
Na podstawie mojego obecnego rozumienia wymazywania (dzięki Jon Skeet i Angelika Langer), tak naprawdę spodziewać się błąd kompilacji jak rzucony przez Java 5 (chyba, że coś się zmieniło w sposobie Java obsługiwane Generics - których nie mogę znaleźć na informacje o wydaniu Java 6). W rzeczywistości, jeśli mogę zmienić typ zwracany jednego z przeciążonych metod:
public static Object method(List<Object> list) ...
public static Object method(List<String> list) ...
Java 6 również nie skompilować z powodu tych samych wymazywania: Wydaje
$ javac TestErasure.java TestErasure.java:5: name clash: method(java.util.List<java.lang.Object>) and method(java.util.List<java.lang.String>) have the same erasure
public static Object method(List<Object> list) {
^
TestErasure.java:10: name clash: method(java.util.List<java.lang.String>) and method(java.util.List<java.lang.Object>) have the same erasure
public static Object method(List<String> list) {
^
2 errors
jakby typ zwracany w Java 6 w jakiś sposób wpływa na wybór, której przeciążonej metody użyć?
Czy ktoś może rzucić światło na to, dlaczego pierwszy przykład działa w Javie 6 - wydaje się, że jest to sprzeczne ze stwierdzoną obsługą przeciążonych ogólnych metod?
Więcej informacji:
sugestia Per Dawida, oryginalny przykład, przestrzegane przez javac 1.6, będzie działać pod Java 1.5:
$ javac -target 1.5 TestErasure.java
$ java -version
java version "1.5.0_19"
$ java TestErasure
method(List<Object> list)
method(List<String> list)
The (usunięte) Typ zwrotny jest częścią m sygnatura ethod we wszystkich wersjach Java. –
Typ zwracany jest częścią deskryptora metody, ale nie sygnaturą metody, prawda? http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20a%20method%20signature? –
@ Tom - Wierzę, że się mylisz - "Definicja: Dwa komponenty deklaracji metody obejmują sygnaturę metody - nazwę metody i typy parametrów." Z http://java.sun.com/docs/books/tutorial/java/javaOO/methods.html. Podpis metody musi być unikalny, aby przeciążanie metody działało i nie zależy od typu zwracanego (przynajmniej w przypadku języka Java). – weiji