2015-08-18 38 views
0

如果你有两个重载的方法,像这样:我怎样才能让一个方法取空值?

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

如果你试图调用methodNamenull你会得到一个错误,指出它的暧昧这是可以理解的,因为它不知道该怎么办哪一种方法。

我知道你可以只投出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

@Andreas,问题是关于如何编写一个可以使用'null'并解决编译器歧义的函数,它不是*关于类型化参数优点的问题。 – par

4

只是做一个方法不带任何参数。

public void methodName(){} 

要求的方法,其must take a null相同要求总是需要5的方法或始终以“foo”的方法。如果传递的参数应该总是包含相同的值,则完全不需要该参数。

如果你被要求将被选择时所传递的参数为空,而不管其类型的方法(即两个方法调用下面需要调用相同的重载方法),

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

这不是因为必须在编译时使用参数的编译时类型来选择要使用的重载方法。在编译时,编译器无法知道在执行该方法时传递的变量包含null。

+1

方法名的'实现(文件)'和'methodName(String)'当然可以做一个空的检查,如果该参数为空,则调用'methodName()',确保你的两个例子以你定义的无参数重载结束。 – Andreas

+0

@Andreas如果所有这些方法都不是“最终”的,那么记录内部呼叫就很重要。 –

+0

没有真正回答OP的问题。他希望有一个通用的'null'处理程序,并且唯一实现这个功能的方法是使用'Object'并测试'null'或downcasts的函数。它*可以*用Java完成。 – par

0

参数通过可以总是总是为空如果它是Object。当你尝试在空引用上运行一个方法时,你会得到一个空指针异常。

所以,public void methodName(File file){}可以被称为methodName(null)没有例外。

然而,

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

将导致空指针异常,如果传递null。

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不能抛出checked异常,所以如果我们希望捕捉IOException异常在future对象,我们多用可赎回。

在Java 8中,您可以使用lambda表达式,但编译器将仍然期望,如果你抛出checked异常返回null作为它的作品了,你必须使用可赎回

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);'因为你仍然需要为重载方法强制转换。 –