2015-08-18 3 views
0

Если у вас есть два перегруженных методов, например:Как я могу заставить метод принять нулевое значение?

public void methodName(File file){} 
public void methodName(String string){} 

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

Я знаю, что вы можете просто указать нуль: methodName((String) null), но как я могу создать метод, специально предназначенный для обработки ситуаций, в которых вы звоните methodName(null)?

Что-то вроде этого:

public void methodName(null null){} 

Как я могу сделать метод, который должен взять нуль?

ответ

0

Как вы видели, компилятор не может разрешить два метода, которые принимают разные объекты при передаче null.

Единственный способ обойти это либо напечатанный, как вы сделали, или иметь метод, который принимает общий Object тип и попытки опущенными:

public void methodName(Object object) { 
    if (object == null) { 
     // do something with null 
    } else if (object instanceof File) { 
     // do something with ((File)object) 
    } else { 
     // do something else 
    } 
} 

Написание кода, который выглядит, как это, как правило, как вонючий, и по уважительной причине. Он быстро усложняется, его сложно поддерживать и т. Д. Лучше всего выбрать тип или изменить сигнатуры методов, чтобы вы (и компилятор) всегда знали, какую функцию следует вызывать для обработки определенного объекта null.

+0

Перегруженный метод с типизированными параметрами гарантирует (и документ), что даны только допустимые типы. – Andreas

+0

Почему downvote? Это функционально правильный код, и он фактически отвечает на заданный вопрос. Я * * * прямо указывал, что в качестве практики программирования он недооценивает и объясняет это. – par

+0

@ Аndreas, вопрос о том, как написать функцию, которая может принимать «null» и разрешать неопределенности компилятора, это * не * вопрос о достоинствах типизированных параметров. – par

4

Просто сделайте метод без каких-либо параметров.

public void methodName(){} 

Требование метод, который must take a null является такой же, как требует способ, который всегда принимает 5 или метод, который всегда принимает «Foo». Если переданный аргумент должен всегда содержать одно и то же значение, вообще нет необходимости в этом аргументе.

И если вы просили метод, который будет выбран, когда переданный аргумент является недействительным, независимо от его типа (т.е. как метод вызывает ниже назвал бы тот же самый перегруженный метод),

File f = null; 
String s = null; 
methodName (f); 
methodName (s); 

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

+1

Реализацию 'имяМетод (File) 'и' methodName (String) ', конечно, каждый из них выполняет нулевую проверку и вызывает' methodName() ', если параметр имеет значение null, гарантируя, что ваши два примера попадут в указанную вами перегрузку без параметров. – Andreas

+0

@ Andreas И если все эти методы не являются «последними», важно документировать внутренние вызовы. –

+0

Не отвечает на вопрос OP. Он хочет иметь общий «нулевой» обработчик, и единственный способ реализовать это с помощью функции, которая принимает «Object» и проверяет «null» или downcasts. Это можно * сделать на Java. – par

0

Аргумент передается может всегда всегда быть пустым если это Object. Это когда вы пытаетесь запустить метод на нулевой ссылке, вы получаете исключение с нулевым указателем.

Таким образом, public void methodName(File file){} можно было бы назвать как: methodName(null).

Однако

public void methodName(File file) { 
    file.delete(); 
} 

приведет исключения нулевого указателя, если нуль передается.

0

Вы не можете написать метод, который конкретно принимает null. Вы должны были бы сделать что-то вроде этого:

methodName(File file) { 
    if(file == null) { 
     someOtherMethod(); 
    } 
    else { 
     // other stuff 
    } 
} 

Но было бы чаще просто иметь methodName(File) ручку null, и документ, что он делает с null. Если у вас есть вызов другого метода, и methodName(File) и someOtherMethod() не являются окончательными, вы должны задокументировать внутренний вызов.

0

Вы не можете этого сделать. Помните, что у вас может быть неявный null. Например:

File file = null; 
methodName(file); 

Однако Java компилятор должен связать вызов конкретного метода подписи, поэтому он должен знать, во время компиляции, был ли Сдал null.

С другой стороны, зачем придерживаться null? Ничто не мешает вам определить специальный тип:

enum Null { NULL } 
public void methodName(File file){} 
public void methodName(String string){} 
public void methodName(Null n) {} 

methodName(Null.NULL); // or methodName(NULL); with import static 
2

Там есть тип, который часто используется для представления null и это Void, где единственным допустимым значением является null.

Вы можете написать

void methodName(Void v); 

Где он обычно используется для общих типов возврата, как.

Future<Void> future = executorService.submit(new Callable<Void>() { 
    public Void call() throws IOException { 
     try(FileInputStream fis = new FileInputStream(filename)) { 
      doSomething(fis); 
     } 
     return null; 
    } 
}); 

// later 
future.get(); 

Вы можете спросить, почему бы не использовать Runnable как мы не должны return null;, однако Runnable не может бросить проверяемое исключение, поэтому мы много используем Callable, если мы ожидаем, чтобы захватить IOException в future объекта.

В Java 8, вы можете использовать лямбды, но компилятор все равно будет ожидать возврат нуля, если вы бросаете проверяемое исключение, как это работает, вы должны использовать отзывной

Future<Void> future = executorService.submit(() -> { 
     try(FileInputStream fis = new FileInputStream(filename)) { 
      doSomething(fis); 
     } 
     return null; 
    }); 
+0

Прошу прощения, я не совсем понимаю, не могу ли я использовать 'methodName (void null)'? Это кажется идеальным – Aequitas

+0

@Aequitas Вы можете сделать 'methodName ((Void) null);' поскольку вам по-прежнему нужен бросок для перегруженных методов. –