我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
还有一种选择:
下面的简单函数有助于隐藏空检查(我不知道为什么,但我没有发现它是同一个公共库的一部分):
public static <T> boolean isNull(T argument) {
return (argument == null);
}
你现在可以写了
if (!isNull(someobject)) {
someobject.doCalc();
}
这是IMO更好的表达方式!=无效的
其他回答
如果您使用(或计划使用)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注释。
使用Java8,您可以将供应商传递给下面这样的助手方法,
if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {
}
上面的代码替换了下面的锅炉板代码,
if(a!=null && a.b()!=null && a.b().c()!=null) {
}
//通用工具.java
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
} catch (NullPointerException var2) {
return Optional.empty();
}
}
对于实用程序类,可以检查参数是否为空。
在所有其他情况下,您可能不必这样做。尽可能使用封装,从而减少您想检查null的地方。
Google集合框架为实现空检查提供了一种良好而优雅的方式。
库类中有一个方法如下:
static <T> T checkNotNull(T e) {
if (e == null) {
throw new NullPointerException();
}
return e;
}
用法是(使用import static):
...
void foo(int a, Person p) {
if (checkNotNull(p).getAge() > a) {
...
}
else {
...
}
}
...
或者在您的示例中:
checkNotNull(someobject).doCalc();
只是永远不要使用null。不要允许。
在我的类中,大多数字段和局部变量都有非空的默认值,我在代码中的任何地方都添加了契约语句(总是在断言上),以确保这是强制执行的(因为它比让它作为NPE出现然后必须解析行号等更简洁、更具表达力)。
一旦我采用了这种做法,我注意到问题似乎会自行解决。你会在开发过程中很早就发现事情,只是偶然发现自己有一个弱点。。更重要的是。。它有助于封装不同模块的关注点,不同模块可以相互“信任”,不再在代码中添加if=nullelse结构!
这是一种防御性编程,从长远来看,代码会更加干净。始终对数据进行净化,例如在这里通过强制执行严格的标准,问题就会消失。
class C {
private final MyType mustBeSet;
public C(MyType mything) {
mustBeSet=Contract.notNull(mything);
}
private String name = "<unknown>";
public void setName(String s) {
name = Contract.notNull(s);
}
}
class Contract {
public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}
合同就像是小型单元测试,即使在生产中也始终在运行,当事情失败时,你知道原因,而不是随机的NPE,你必须设法弄清楚。