Перегрузка метода для нулевого аргумента
Я добавил три метода с параметрами:
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);
Хотя вы все еще передаете значение null
Java точно знает, какой метод вызывать, так как он будет учитывать тип переменной.
Каждая пара этих трех методов сама по себе неоднозначна, когда вызывается с 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, поэтому они неоднозначны.