检查“get”链要求为空
假设我想执行以下命令:
house.getFloor(0).getWall(WEST).getDoor().getDoorknob();
为了避免 NullPointerException,我必须执行以下操作:
if (house != null && house.getFloor(0) && house.getFloor(0).getWall(WEST) != null
&& house.getFloor(0).getWall(WEST).getDoor() != null) ...
是否有一种方法或现有的 Utils 类可以更优雅地执行此操作,让我们说类似以下内容?
checkForNull(house.getFloor(0).getWall(WEST).getDoor().getDoorknob());
Let's say I'd like to perform the following command:
house.getFloor(0).getWall(WEST).getDoor().getDoorknob();
To avoid a NullPointerException, I'd have to do the following if:
if (house != null && house.getFloor(0) && house.getFloor(0).getWall(WEST) != null
&& house.getFloor(0).getWall(WEST).getDoor() != null) ...
Is there a way or an already existing Utils class that does this more elegantly, let's say something like the following?
checkForNull(house.getFloor(0).getWall(WEST).getDoor().getDoorknob());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
如果您无法避免违反所选答案中所述的德墨忒尔定律 (LoD),并且Java 8 介绍 可选,这可能是处理像您这样的获取链中的空值的最佳实践。
Optional
类型将使您能够连续传输多个映射操作(其中包含 get 调用)。空检查会在后台自动处理。例如,当对象未初始化时,不会执行 print() 操作,也不会抛出任何异常。这一切我们都可以在幕后温和地处理。当对象初始化时,将进行打印。
因此,使用您的 getters 链,它将如下所示:
它的返回将类似于
Optional
,这将使您的工作更加安全,而不必担心 null 异常。In case you can't avoid breaking Law of Demeter (LoD) as stated in the chosen answer, and with Java 8 introducing Optional, it would be probably the best practice to handle nulls in chains of gets such as yours.
The
Optional
type will enable you to pipe multiple map operations (which contain get calls) in a row. Null checks are automatically handled under the hood.For example, when the objects aren't initialized, no print() will be made and no Exceptions will be thrown. It all we be handled gently under the hood. When objects are initialized, a print will be made.
So, with your getters chain it will look like this:
The return of it will be something like
Optional<Door>
which will allow you much safer work without worrying of null exceptions.为了检查获取链是否为 null,您可能需要从闭包调用代码。闭包调用代码将如下所示:
您可以使用以下语法调用它:
该代码也是类型安全的,并且通常按预期工作:
您可以将 opt 方法放入共享 util 类中,并在应用程序中的任何地方使用它。
In order to check a chain of gets for null you may need to call your code from a closure. The closure call code will look like this:
And you call it using the following syntax:
This code is also type safe and in general works as intended:
You may place opt method into shared util class and use it everywhere in your application.
最好的方法是避免链条。如果您不熟悉迪米特定律 (LoD),我认为您应该熟悉。您给出了一个完美的消息链示例,该消息链与类过于密切,它没有必要了解任何内容。
德墨忒尔定律:http://en.wikipedia.org/wiki/Law_of_Demeter
The best way would be to avoid the chain. If you aren't familiar with the Law of Demeter (LoD), in my opinion you should. You've given a perfect example of a message chain that is overly intimate with classes that it has no business knowing anything about.
Law of Demeter: http://en.wikipedia.org/wiki/Law_of_Demeter
当然,您可以简单地将整个表达式包装在 try-catch 块中,但这是一个坏主意。更简洁的是空对象模式。这样,如果你的房子没有 0 层,它只会返回一个像普通楼层一样的楼层,但没有实际内容;当楼层被要求提供它们没有的墙时,会返回类似的“空”墙等。
You could of course simply wrap the whole expression up in a try-catch block, but that's a bad idea. Something cleaner is the Null object pattern. With that, if your house doesn't have floor 0, it just returns a Floor that acts like a regular Floor, but has no real content; Floors, when asked for Walls they don't have, return similar "Null" Walls, etc, down the line.
确保逻辑上不能为
null
的内容并非如此。例如 - 房子总是有一面西墙。为了避免状态中出现此类异常,您可以使用方法来检查您期望的状态是否存在:这本质上是空检查,但可能并不总是如此。
重点是,如果您有
null
,您应该采取一些措施。例如 -return
或抛出IllegalStateException
而你不应该做的 - 不要捕获
NullPointerException
。运行时异常不适合捕获 - 不希望您能够从中恢复,依赖逻辑流的异常也不是一个好的实践。想象一下,您实际上并不希望某些内容为null
,并且您捕获(并记录)一个NullPointerException
。这不会是非常有用的信息,因为此时很多东西都可能为null
。Make sure things that can't logically be
null
are not. For example - a house always has a West wall. In order to avoid such exceptions in state, you can have methods to check whether the state you expect is present:This is essentially a null-check, but might not always be.
The point is that you should do something in case you have a
null
. For example -return
or throw anIllegalStateException
And what you shouldn't do - don't catch
NullPointerException
. Runtime exceptions are not for catching - it is not expected that you can recover from them, nor it is a good practice to rely on exceptions for the logic flow. Imagine that you actually don't expect something to benull
, and you catch (and log) aNullPointerException
. This will not be very useful information, since many things can benull
at that point.对我来说更好的解决方案是使用 java.util.Optional.map(..) 链接这些检查: https://stackoverflow.com /a/67216752/1796826
Better solution for me is to use java.util.Optional.map(..) to chain these checks : https://stackoverflow.com/a/67216752/1796826
您无法编写任何
checkForNull
方法来实现此目的(这根本不是 Java 中方法调用和参数求值的工作方式)。您可以将链接语句分解为多个语句,并在每一步进行检查。然而,也许更好的解决方案是首先不让这些方法返回 null。您可能想使用一种名为 空对象模式 的东西。
相关问题
!= null
语句?There is no
checkForNull
method that you can write that will facilitate this (that's simply not how method invokation and argument evaluation works in Java).You can break down the chained statements into multiple statements, checking at every step. However, perhaps a better solution is to not have these methods return
null
in the first place. There is something called the Null Object Pattern that you may want to use instead.Related questions
!= null
statements in Java?您可能有一个如下所示的通用方法:
所以现在您可以这样做
You could potentially have a generic method like below:
So now you would be able to do
使用供应商实现 nullPointer try/catch,您可以将所有 get 链发送给它
,然后以这种方式调用它。
implementing nullPointer try/catch with a Supplier you can send it all chain of get
and then call it in this way.
非常老的问题,但仍然添加我的建议:
我建议不要在一个方法调用链中从房子深处获取 DoorKnob,您应该尝试让 DoorKnob 从调用代码提供给此类,或者通过创建一个专门用于此目的的中央查找设施(例如 DoorKnob 服务)
松散耦合设计的简化示例:
Very old question, but still adding my suggestion:
I would suggest instead of getting the DoorKnob from deep within the House in one method call chain, you should try to let the DoorKnob be provided to this class from the calling code, or by creating a central lookup facility specifically for this purpose (e.g. a DoorKnob service)
Simplified example of design with loose coupling: