Перегрузка метода для нулевого аргумента

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

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 ответов

Решение

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);

Хотя вы все еще передаете значение nullJava точно знает, какой метод вызывать, так как он будет учитывать тип переменной.

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

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

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

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

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

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

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

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

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 называются нулевыми, поэтому неоднозначность с char[] и Integer

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

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

Другие вопросы по тегам