Это зависит от того, как вы хотите вызывать эти методы. Если вы хотите вызвать эти методы из другого исходного кода Java , то он считается недействительным по причинам, показанным в ответ Эдвина . Это ограничение языка Java.
Однако не все классы должны быть сгенерированы из исходного кода Java (рассмотрите все языки, которые используют JVM в качестве среды выполнения: JRuby, Jython и т. Д.). На уровне байт-кода JVM может устранить неоднозначность двух методов, поскольку инструкции байт-кода указывают возвращаемый тип , который они ожидают. Например, вот класс, написанный на Jasmin , который может вызывать любой из этих методов:
.class public CallAmbiguousMethod
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
.limit stack 3
.limit locals 1
; Call the method that returns String
aconst_null
invokestatic TestWillThatCompile/f(Ljava/util/List;)Ljava/lang/String;
; Call the method that returns Integer
aconst_null
invokestatic TestWillThatCompile/f(Ljava/util/List;)Ljava/lang/Integer;
return
.end method
Я компилирую его в файл класса, используя следующую команду:
java -jar jasmin.jar CallAmbiguousMethod.j
И позвоните, используя:
java CallAmbiguousMethod
Вот, вывод:
> java CallAmbiguousMethod
strings
numbers
Обновление
Саймон опубликовал пример программы , которая вызывает эти методы:
import java.util.Arrays;
import java.util.List;
class RealyCompilesAndRunsFine {
public static String f(List<String> list) {
return list.get(0);
}
public static Integer f(List<Integer> list) {
return list.get(0);
}
public static void main(String[] args) {
final String string = f(Arrays.asList("asdf"));
final Integer integer = f(Arrays.asList(123));
System.out.println(string);
System.out.println(integer);
}
}
Вот сгенерированный байт-код Java:
>javap -c RealyCompilesAndRunsFine
Compiled from "RealyCompilesAndRunsFine.java"
class RealyCompilesAndRunsFine extends java.lang.Object{
RealyCompilesAndRunsFine();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public static java.lang.String f(java.util.List);
Code:
0: aload_0
1: iconst_0
2: invokeinterface #2, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
7: checkcast #3; //class java/lang/String
10: areturn
public static java.lang.Integer f(java.util.List);
Code:
0: aload_0
1: iconst_0
2: invokeinterface #2, 2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
7: checkcast #4; //class java/lang/Integer
10: areturn
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: anewarray #3; //class java/lang/String
4: dup
5: iconst_0
6: ldc #5; //String asdf
8: aastore
9: invokestatic #6; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
12: invokestatic #7; //Method f:(Ljava/util/List;)Ljava/lang/String;
15: astore_1
16: iconst_1
17: anewarray #4; //class java/lang/Integer
20: dup
21: iconst_0
22: bipush 123
24: invokestatic #8; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
27: aastore
28: invokestatic #6; //Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
31: invokestatic #9; //Method f:(Ljava/util/List;)Ljava/lang/Integer;
34: astore_2
35: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
38: aload_1
39: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
42: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
45: aload_2
46: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
49: return
Оказывается, компилятор Sun генерирует байт-код, необходимый для устранения неоднозначности методов (см. Инструкции 12 и 31 в последнем методе).
Обновление № 2
Спецификация языка Java предполагает, что на самом деле это может быть действительный исходный код Java. На странице 449 (§15.12 Выражения вызова метода) мы видим это:
Вполне возможно, что ни один метод не является наиболее специфичным, потому что есть два или
больше методов, которые максимально специфичны. В этом случае:
- Если все максимально специфические методы имеют сигнатуры, эквивалентные переопределению (§8.4.2),
затем:
- Если точно один из максимально специфических методов не объявлен абстрактным,
это самый специфический метод.
- В противном случае, если все максимально конкретные методы объявлены абстрактными,
и сигнатуры всех максимально специфических методов имеют одинаковые
erasure (§4.6), , тогда наиболее конкретный метод выбирается произвольно среди
подмножество максимально специфических методов, которые имеют наиболее специфические
тип возврата . Тем не менее, наиболее конкретный метод считается бросить
проверенное исключение, если и только если это исключение или его удаление объявлено в
предложения throws каждого из максимально специфических методов.
- В противном случае мы говорим, что вызов метода неоднозначен, и время компиляции
возникает ошибка.
Если я не ошибаюсь, это поведение должно применяться только к методам, объявленным как абстрактные ...
Обновление № 3
Благодаря комментарию ILMTitan:
@ Адам Пейнтер: Ваш жирный текст делает
не имеет значения, потому что это только случай
когда два метода
эквивалентный переопределению, который показал Дэн
был не тот случай. Таким образом
определяющим фактором должно быть, если JLS
принимает во внимание общие типы, когда
определение наиболее конкретного метода. -
ILMTitan