Я столкнулся с проблемой в Java Generics, в которой тот же код будет компилироваться и отлично работать в Java 6, но не сможет скомпилироваться из-за того же стирания в Java 5. У меня есть файл TestErasure.java, который имеет перегруженный метод, называемый "метод":
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>());
}
}
В Java 5 я получаю ожидаемую ошибку компиляции, заявляя, что стирание "метода" одинаково:
$ 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
Однако Java 6 может компилировать и запускать этот же код.
$ javac -version
javac 1.6.0_16
$ javac TestErasure.java
$ java TestErasure
method(List<Object> list)
method(List<String> list)
Основываясь на моем нынешнем понимании стираний (благодаря Jon Skeet и Angelika Langer), я на самом деле ожидал ошибку компиляции, которая была выбрана Java 5 (если только что-то не изменилось в том, как Java обрабатывал Generics, чего я не могу найти в заметках о выпуске Java 6). Фактически, если я изменяю тип возвращаемого значения одного из перегруженных методов:
public static Object method(List<Object> list) ...
public static Object method(List<String> list) ...
Java 6 также не может скомпилироваться из-за одинаковых стираний:
$ 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
Кажется, что возвращаемый тип в Java 6 каким-то образом влияет на выбор того, какой перегруженный метод использовать?
Может ли кто-то пролить свет на то, почему первый пример работает на Java 6 - похоже, это противоречит заявленной обработке перегруженных общих методов?
Дополнительная информация:
По предложению Дэвида исходный пример, выполняемый javac 1.6, будет работать под 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)