我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
如果您使用(或计划使用)JetBrains IntelliJ IDEA、Eclipse或Netbeans等Java IDE或findbugs等工具,那么您可以使用注释来解决这个问题。
基本上,你有@Nullable和@NotNull。
您可以在方法和参数中使用,如下所示:
@NotNull public static String helloWorld() {
return "Hello World";
}
or
@Nullable public static String helloWorld() {
return "Hello World";
}
第二个示例无法编译(在IntelliJ IDEA中)。
在另一段代码中使用第一个helloWorld()函数时:
public static void main(String[] args)
{
String result = helloWorld();
if(result != null) {
System.out.println(result);
}
}
现在IntelliJ IDEA编译器将告诉您,检查是无用的,因为helloWorld()函数永远不会返回null。
使用参数
void someMethod(@NotNull someParameter) { }
如果你写的东西像:
someMethod(null);
这无法编译。
最后一个使用@Nullable的示例
@Nullable iWantToDestroyEverything() { return null; }
这样做
iWantToDestroyEverything().something();
你可以肯定这不会发生。:)
这是一个很好的方法,可以让编译器检查比通常更多的东西,并强制执行您的契约以使其更强大。不幸的是,并非所有编译器都支持它。
在IntelliJ IDEA 10.5及更高版本中,他们添加了对任何其他@Nullable@NotNull实现的支持。
查看博客文章更灵活和可配置的@Nullable/@NotNull注释。
其他回答
您可以考虑空对象是bug的情况,而不是空对象模式(有其用途)。
当抛出异常时,检查堆栈跟踪并解决错误。
我可以更笼统地回答吗!
当方法以我们不期望的方式获取参数时,我们通常会遇到这个问题(错误的方法调用是程序员的错误)。例如:您希望得到一个对象,而得到一个null。您希望得到一个至少包含一个字符的字符串,而得到一个空字符串。。。
因此:
if(object == null){
//you called my method badly!
}
or
if(str.length() == 0){
//you called my method badly again!
}
他们都希望在执行任何其他函数之前确保我们收到了有效的参数。
如其他一些答案中所述,为了避免上述问题,您可以遵循契约设计模式。请参见http://en.wikipedia.org/wiki/Design_by_contract.
要在java中实现这种模式,可以使用javax.annotation.NotNull等核心java注释,或者使用Hibernate Validator等更复杂的库。
只是一个示例:
getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)
现在,您可以安全地开发方法的核心函数,而无需检查输入参数,它们可以保护您的方法不受意外参数的影响。
您可以更进一步,确保在应用程序中只能创建有效的pojo。(来自hibernate验证器站点的示例)
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
// ...
}
如果您使用(或计划使用)JetBrains IntelliJ IDEA、Eclipse或Netbeans等Java IDE或findbugs等工具,那么您可以使用注释来解决这个问题。
基本上,你有@Nullable和@NotNull。
您可以在方法和参数中使用,如下所示:
@NotNull public static String helloWorld() {
return "Hello World";
}
or
@Nullable public static String helloWorld() {
return "Hello World";
}
第二个示例无法编译(在IntelliJ IDEA中)。
在另一段代码中使用第一个helloWorld()函数时:
public static void main(String[] args)
{
String result = helloWorld();
if(result != null) {
System.out.println(result);
}
}
现在IntelliJ IDEA编译器将告诉您,检查是无用的,因为helloWorld()函数永远不会返回null。
使用参数
void someMethod(@NotNull someParameter) { }
如果你写的东西像:
someMethod(null);
这无法编译。
最后一个使用@Nullable的示例
@Nullable iWantToDestroyEverything() { return null; }
这样做
iWantToDestroyEverything().something();
你可以肯定这不会发生。:)
这是一个很好的方法,可以让编译器检查比通常更多的东西,并强制执行您的契约以使其更强大。不幸的是,并非所有编译器都支持它。
在IntelliJ IDEA 10.5及更高版本中,他们添加了对任何其他@Nullable@NotNull实现的支持。
查看博客文章更灵活和可配置的@Nullable/@NotNull注释。
我喜欢Nat Pryce的文章。以下是链接:
用多态调度避免空值避免使用“告诉,不要问”风格的null
在文章中,还有一个指向Java Maybe Type的Git存储库的链接,我觉得这很有趣,但我不认为单独使用它会降低检查代码膨胀。在互联网上做了一些研究之后,我想主要通过仔细设计可以减少空码膨胀。
Java中常见的“问题”确实存在。
首先,我的想法是:
我认为,当传递NULL时,如果NULL不是有效值,“吃掉”某些东西是不好的。如果您退出方法时没有出现某种错误,那么这意味着您的方法中没有任何错误,这是不正确的。在这种情况下,您可能会返回null,在接收方法中,您再次检查null,并且它永远不会结束,结果是“if!=null”等。。
因此,IMHO,null必须是阻止进一步执行的关键错误(即,null不是有效值)。
我解决这个问题的方法是:
首先,我遵循以下惯例:
所有公共方法/API始终检查其参数是否为空所有私有方法都不检查null,因为它们是受控制的方法(如果上面没有处理null指针异常,就让它终止)唯一不检查null的其他方法是实用程序方法。他们是公开的,但如果你出于某种原因打电话给他们,你知道你通过了哪些参数。这就像试图在水壶里烧水而不提供水。。。
最后,在代码中,public方法的第一行如下所示:
ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();
注意,addParam()返回self,这样您就可以添加更多的参数来检查。
如果任何参数为空,方法validate()将抛出checked ValidationException(checked或unchecked更多是设计/品味问题,但我的ValidationException已选中)。
void validate() throws ValidationException;
例如,如果“计划”为空,则消息将包含以下文本:
“参数[plans]遇到非法参数值null”
正如您所看到的,用户消息需要addParam()方法中的第二个值(字符串),因为即使有反射(无论如何都不是本文的主题…),也无法轻松检测传入的变量名。
是的,我们知道,在这一行之外,我们将不再遇到空值,因此我们只需安全地调用这些对象上的方法。
这样,代码就干净、易于维护和可读。