36 java null nullpointerexception
假设我想执行以下命令:
house.getFloor(0).getWall(WEST).getDoor().getDoorknob();
Run Code Online (Sandbox Code Playgroud)
为了避免NullPointerException,我必须在以下情况下执行以下操作:
if (house != null && house.getFloor(0) && house.getFloor(0).getWall(WEST) != null
&& house.getFloor(0).getWall(WEST).getDoor() != null) ...
Run Code Online (Sandbox Code Playgroud)
是否有一种方法或已经存在的Utils类更优雅地执行此操作,让我们说类似下面的内容?
checkForNull(house.getFloor(0).getWall(WEST).getDoor().getDoorknob());
Run Code Online (Sandbox Code Playgroud)
Joh*_*nny 42
如果您无法避免违反所选答案中所述的Demeter法则(LoD),并且Java 8引入了Optional,那么处理像你这样的获取链中的空值可能是最好的做法.
该Optional类型将使您能够连续管道多个映射操作(包含get调用).无效检查在引擎盖下自动处理.
例如,如果未初始化对象,则不会生成print(),也不会抛出异常.这一切都在引擎盖下轻轻处理.初始化对象时,将进行打印.
System.out.println("----- Not Initialized! -----");
Optional.ofNullable(new Outer())
.map(out -> out.getNested())
.map(nest -> nest.getInner())
.map(in -> in.getFoo())
.ifPresent(foo -> System.out.println("foo: " + foo)); //no print
System.out.println("----- Let's Initialize! -----");
Optional.ofNullable(new OuterInit())
.map(out -> out.getNestedInit())
.map(nest -> nest.getInnerInit())
.map(in -> in.getFoo())
.ifPresent(foo -> System.out.println("foo: " + foo)); //will print!
class Outer {
Nested nested;
Nested getNested() {
return nested;
}
}
class Nested {
Inner inner;
Inner getInner() {
return inner;
}
}
class Inner {
String foo = "yeah!";
String getFoo() {
return foo;
}
}
class OuterInit {
NestedInit nested = new NestedInit();
NestedInit getNestedInit() {
return nested;
}
}
class NestedInit {
InnerInit inner = new InnerInit();
InnerInit getInnerInit() {
return inner;
}
}
class InnerInit {
String foo = "yeah!";
String getFoo() {
return foo;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,对于你的getters链,它将如下所示:
Optional.ofNullable(house)
.map(house -> house.getFloor(0))
.map(floorZero -> floorZero.getWall(WEST))
.map(wallWest -> wallWest.getDoor())
.map(door -> wallWest.getDoor())
Run Code Online (Sandbox Code Playgroud)
它的返回将是一个类似的东西Optional<Door>,将允许你更安全的工作,而不用担心空例外.
Jer*_*ing 16
最好的方法是避免链条.如果您不熟悉得墨忒耳法(LoD),我认为您应该这样做.您已经给出了一个完整的消息链示例,该消息链与类没有业务知道的类过于亲密.
得墨忒耳法则:http://en.wikipedia.org/wiki/Law_of_Demeter
小智 15
为了检查gets的链是否为null,您可能需要从闭包中调用您的代码.闭包调用代码如下所示:
public static <T> T opt(Supplier<T> statement) {
try {
return statement.get();
} catch (NullPointerException exc) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用以下语法调用它:
Doorknob knob = opt(() -> house.getFloor(0).getWall(WEST).getDoor().getDoorknob());
Run Code Online (Sandbox Code Playgroud)
此代码也是类型安全的,通常按预期工作:
您可以将opt方法放入共享的util类中,并在应用程序的任何位置使用它.
确保逻辑上不可能的事情null不是。例如 - 房子总是有一面西墙。为了避免状态中的此类异常,您可以使用方法来检查您期望的状态是否存在:
if (wall.hasDoor()) {
wall.getDoor().etc();
}
Run Code Online (Sandbox Code Playgroud)
这本质上是一个空检查,但可能并不总是如此。
关键是你应该做一些事情,以防你有一个null. 例如 -return或抛出IllegalStateException
而你不应该做的——不要抓住NullPointerException。运行时异常不是用于捕获的 - 不希望您可以从它们中恢复,依赖逻辑流的异常也不是一个好习惯。想象一下,您实际上并不期望某事是null,并且您捕获(并记录)了 a NullPointerException。这不会是非常有用的信息,因为null此时可能会有很多事情。