如何使方法采用空值?
How can I make a method take a null value?
如果你有两个像这样的重载方法:
public void methodName(File file){}
public void methodName(String string){}
如果您尝试使用 null
调用 methodName
,您将收到一条错误消息,指出它不明确,这是可以理解的,因为它不知道要执行哪种方法。
我知道你可以只转换 null: methodName((String) null)
但我如何创建一个方法来专门处理你调用 methodName(null)
的情况?
像这样:
public void methodName(null null){}
如何创建一个必须为 null 的方法?
只做一个没有任何参数的方法。
public void methodName(){}
要求 must take a null
的方法与要求始终采用 5 的方法或始终采用 "foo" 的方法相同。如果传递的参数应该始终包含相同的值,则根本不需要该参数。
并且如果您要求的是只要传递的参数为 null 就会被选择的方法,无论其类型如何(即下面的两个方法调用都会调用相同的重载方法),
File f = null;
String s = null;
methodName (f);
methodName (s);
这是不可能的,因为要使用的重载方法必须在编译时使用参数的编译时类型来选择。在编译时,编译器无法知道执行方法时传递的变量是否包含 null。
传递的参数可以始终始终为空如果它是Object
。当您在空引用上尝试 运行 一个方法时,您会得到一个空指针异常。
所以,public void methodName(File file){}
可以无一例外地称为methodName(null)
。
然而,
public void methodName(File file) {
file.delete();
}
传null会导致空指针异常
如您所见,当您传递 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
对象。
您不能编写专门采用 null
的方法。你必须做这样的事情:
methodName(File file) {
if(file == null) {
someOtherMethod();
}
else {
// other stuff
}
}
但更常见的做法是让 methodName(File)
处理 null
,并记录它对 null
的作用。如果你让它调用另一个方法并且 methodName(File)
和 someOtherMethod()
不是最终的,你应该记录内部调用。
你不能这样做。请记住,您可能有隐式 null
。例如:
File file = null;
methodName(file);
然而,Java编译器必须link调用特定的方法签名,所以它应该在编译时知道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
有一种类型常用于表示 null
,这是 Void
,其中唯一有效值是 null
。
你可以写
void methodName(Void v);
它通常用于通用 return 类型,例如。
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 future
对象中的 IOException。
在 Java 8 中,您可以使用 lambda,但如果您抛出已检查的异常,编译器仍会期望 return 为 null,因为它必须使用 Callable
Future<Void> future = executorService.submit(() -> {
try(FileInputStream fis = new FileInputStream(filename)) {
doSomething(fis);
}
return null;
});
如果你有两个像这样的重载方法:
public void methodName(File file){}
public void methodName(String string){}
如果您尝试使用 null
调用 methodName
,您将收到一条错误消息,指出它不明确,这是可以理解的,因为它不知道要执行哪种方法。
我知道你可以只转换 null: methodName((String) null)
但我如何创建一个方法来专门处理你调用 methodName(null)
的情况?
像这样:
public void methodName(null null){}
如何创建一个必须为 null 的方法?
只做一个没有任何参数的方法。
public void methodName(){}
要求 must take a null
的方法与要求始终采用 5 的方法或始终采用 "foo" 的方法相同。如果传递的参数应该始终包含相同的值,则根本不需要该参数。
并且如果您要求的是只要传递的参数为 null 就会被选择的方法,无论其类型如何(即下面的两个方法调用都会调用相同的重载方法),
File f = null;
String s = null;
methodName (f);
methodName (s);
这是不可能的,因为要使用的重载方法必须在编译时使用参数的编译时类型来选择。在编译时,编译器无法知道执行方法时传递的变量是否包含 null。
传递的参数可以始终始终为空如果它是Object
。当您在空引用上尝试 运行 一个方法时,您会得到一个空指针异常。
所以,public void methodName(File file){}
可以无一例外地称为methodName(null)
。
然而,
public void methodName(File file) {
file.delete();
}
传null会导致空指针异常
如您所见,当您传递 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
对象。
您不能编写专门采用 null
的方法。你必须做这样的事情:
methodName(File file) {
if(file == null) {
someOtherMethod();
}
else {
// other stuff
}
}
但更常见的做法是让 methodName(File)
处理 null
,并记录它对 null
的作用。如果你让它调用另一个方法并且 methodName(File)
和 someOtherMethod()
不是最终的,你应该记录内部调用。
你不能这样做。请记住,您可能有隐式 null
。例如:
File file = null;
methodName(file);
然而,Java编译器必须link调用特定的方法签名,所以它应该在编译时知道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
有一种类型常用于表示 null
,这是 Void
,其中唯一有效值是 null
。
你可以写
void methodName(Void v);
它通常用于通用 return 类型,例如。
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 future
对象中的 IOException。
在 Java 8 中,您可以使用 lambda,但如果您抛出已检查的异常,编译器仍会期望 return 为 null,因为它必须使用 Callable
Future<Void> future = executorService.submit(() -> {
try(FileInputStream fis = new FileInputStream(filename)) {
doSomething(fis);
}
return null;
});