Перегрузка метода для нулевого аргумента - PullRequest
123 голосов
/ 08 марта 2011

Я добавил три метода с параметрами:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

Когда я вызываю doSomething(null), компилятор выдает ошибку как неоднозначные методы . Так проблема в том, что методы Integer и char[] или методы Integer и Object?

Ответы [ 7 ]

200 голосов
/ 08 марта 2011

Java всегда будет пытаться использовать наиболее конкретную применимую версию метода, которая доступна (см. JLS §15.12.2 ).

Object, char[] и Integer могут принимать null в качестве допустимого значения. Поэтому применимы все 3 версии, поэтому Java придется искать наиболее конкретную.

Поскольку Object является супертипом char[], версия массива более специфична, чем Object -версия. Поэтому, если существуют только эти два метода, будет выбрана версия char[].

Когда доступны обе версии char[] и Integer, тогда обе обе являются более конкретными, чем Object, но ни одна не является более конкретной, чем другая, поэтому Java не может решить, какая один позвонить. В этом случае вам придется явно указать, какой из них вы хотите вызвать, приведя аргумент к соответствующему типу.

Обратите внимание, что на практике эта проблема встречается гораздо реже, чем можно подумать. Причина этого в том, что это происходит только тогда, когда вы явно вызываете метод с null или с переменной довольно неопределенного типа (например, Object).

Наоборот, следующий вызов был бы совершенно однозначным:

char[] x = null;
doSomething(x);

Хотя вы по-прежнему передаете значение null, Java точно знает, какой метод вызывать, поскольку он будет учитывать тип переменной.

40 голосов
/ 08 марта 2011

Каждая пара этих трех методов сама по себе неоднозначна при вызове с аргументом null. Потому что каждый тип параметра является ссылочным типом.

Ниже приведены три способа вызова вашего конкретного метода с нулевым значением.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

Могу ли я предложить устранить эту двусмысленность, если вы действительно планируете вызывать эти методы с null аргументами. Такой дизайн вызывает ошибки в будущем.

4 голосов
/ 08 марта 2011

null - допустимое значение для любого из трех типов; поэтому компилятор не может решить, какую функцию использовать. Вместо этого используйте что-то вроде doSomething((Object)null) или doSomething((Integer)null).

2 голосов
/ 08 марта 2011

Каждый класс в Java расширяет класс Object. Даже класс Integer также расширяет объект.Следовательно, и объект, и целое число рассматриваются как экземпляр объекта.Поэтому, когда вы передаете null в качестве параметра, компилятор запутывается в том, какой метод объекта вызывать, т. Е. С параметром Object или параметром Integer, поскольку оба они являются объектом, а их ссылка может быть нулевой.Но примитивы в Java не расширяют Object.

1 голос
/ 30 июля 2014

Я пробовал это, и когда есть ровно одна пара перегруженных методов и один из них имеет тип параметра Object, тогда компилятор всегда будет выбирать метод с более конкретным типом.Но когда существует более одного определенного типа, компилятор выдает неоднозначную ошибку метода.

Поскольку это событие времени компиляции, это может произойти только тогда, когда один намеренно передает значение null этому методу.Если это сделано намеренно, то лучше перегрузить этот метод снова без параметров или вообще создать другой метод.

0 голосов
/ 04 августа 2018
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

Выход Int равен null, поэтому неоднозначность с char [] и Integer

0 голосов
/ 04 ноября 2017

существует неоднозначность из-за doSomething (char [] obj) и doSomething (Integer obj).

char [] и Integer оба превосходят ноль, поэтому они неоднозначны.

...