2016-03-23 4 views
10

Следующий код печатает "String"Почему и как этот код Java компилируется?

public class Riddle { 

    public static void main(String[] args) { 
     hello(null); 
    } 

    public static void hello(Object o) { 
     System.out.println("Object"); 
    } 


    public static void hello(String s) { 
     System.out.println("String"); 
    } 

} 

Почему скомпилировать этот код? Не является null неоднозначно?

Например, следующий код НЕ компилируется из-за неоднозначной подписи.

public class Riddle { 

    public static void main(String[] args) { 
     hello(null); 
    } 

    public static void hello(Object o) { 
     System.out.println("Object"); 
    } 

    public static void hello(Integer o) { 
     System.out.println("Integer"); 
    } 

    public static void hello(String s) { 
     System.out.println("String"); 
    } 

} 

Может кто-нибудь объяснить, почему первый пример может скомпилироваться без двусмысленных ошибок?

+3

«null» - это просто параметр. Во втором случае подпись метода «Объект» не может быть разрешена в отношении двух других. –

+2

Поздравляю, я думаю, вы нашли одну из реальных дыр в теории типов Java. В общем, «Null» - это нечто вроде странного существа, которое набирает системы. Если вы заинтересованы в этом, вы можете проверить тип Option, который используют некоторые языки ... Я лично считаю, что это действительно хорошая функция, и хотелось бы, чтобы не было слишком поздно переносить его на Java. –

+5

См. Также http://stackoverflow.com/questions/2608394/how-is-ambiguity-in-selecting-from-overloaded-methods-resolved-in-java или также http://stackoverflow.com/questions/1545501/ которая-перегрузка будет-получить выбранный-для-нуль-в-Java – Philipp

ответ

1

Во втором случае не компилируется, поскольку компилятор не может решить между методом, который принимает целое и метод, который принимает строку, где, как и в случае первого компилятор может понять это ,

Код: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2

0

пожалуйста, см JLS §15.12.2

следующий порядок метода разрешающего для вызова цели важно когда тот же тип данных типа есть,

  1. (для примитивного типа данных) точные данные -type, а затем вызовите его. 1.1 Если нет, тогда позвоните более широко, тогда этот доступный тип данных затем вызовите его.
  2. соответствует типу Wrapper типа Data или его родительскому элементу, если выше не удалось.
  3. Vararg этого типа данных будет соответствовать, если выше 2-неудачно.
Смежные вопросы