Java“?”检查 null 的运算符 - 它是什么? (不是三元!)
我正在阅读 一篇 InfoWorld 文章(链接到 Wayback machine,因为摘录已被删除),并发现了这个小花絮:
采用最新版本的 Java, 尝试进行空指针检查 通过提供简写语法更容易 用于无休止的指针测试。只是 给每个方法加一个问号 调用自动包含一个 测试空指针,替换 if-then 语句的老鼠巢,例如 作为:
public String getPostcode(Person person) { 字符串 ans= null; 如果(人!=空){ 姓名 nm= person.getName(); if (nm!= null) { ans= nm.getPostcode(); } } 返回答案 }
这样:
public String getFirstName(Person person) { 返回 person?.getName()?.getGivenName(); }
我在互联网上进行了搜索(好吧,我花了至少 15 分钟在谷歌上搜索“java 问号”的变体),但一无所获。所以,我的问题是:有这方面的官方文档吗?我发现 C# 有一个类似的运算符(“??”运算符),但我想获取我正在使用的语言的文档。或者,这只是我已经使用的三元运算符的使用以前从未见过。
谢谢!
I was reading an InfoWorld article (link to Wayback machine since the excerpt was since removed), and came across this little tidbit:
Take the latest version of Java, which
tries to make null-pointer checking
easier by offering shorthand syntax
for the endless pointer testing. Just
adding a question mark to each method
invocation automatically includes a
test for null pointers, replacing a
rat's nest of if-then statements, such
as:public String getPostcode(Person person) { String ans= null; if (person != null) { Name nm= person.getName(); if (nm!= null) { ans= nm.getPostcode(); } } return ans }With this:
public String getFirstName(Person person) { return person?.getName()?.getGivenName(); }
I've scoured the internet (okay, I spent at least 15 minutes googling variations on "java question mark") and got nothing. So, my question: is there any official documentation on this? I found that C# has a similar operator (the "??" operator), but I'd like to get the documentation for the language I'm working in. Or, is this just a use of the ternary operator that I've never seen before.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
Java 没有精确语法,但从 JDK-8 开始,我们有可选 API 以及我们可以使用的各种方法。因此,C# 版本使用 null 条件运算符:
在 Java 中可以使用 可选 API:
如果
person
、getName
或getGivenName
中的任何一个为 null,则返回 null。Java does not have the exact syntax but as of JDK-8, we have the Optional API with various methods at our disposal. So, the C# version with the use of null conditional operator:
can be written as follows in Java with the Optional API:
if any of
person
,getName
orgetGivenName
is null then null is returned.Java 7 中有一个提案,但被拒绝了:
http://tech.puredanger.com/java7/#null
There was a proposal for it in Java 7, but it was rejected:
http://tech.puredanger.com/java7/#null
这实际上是 Groovy 的安全取消引用运算符。您不能在纯 Java 中使用它(遗憾的是),因此该帖子完全是错误的(或者更可能有点误导,如果它声称 Groovy 是“Java 的最新版本”)。
That's actually Groovy's safe-dereference operator. You can't use it in pure Java (sadly), so that post is simply wrong (or more likely slightly misleading, if it's claiming Groovy to be the "latest version of Java").
请参阅:https://blogs.oracle.com /darcy/project-coin:-the-final- Five-or-so(特别是“Elvis 和其他 null 安全运算符”)。
结果是 Java 7 考虑了此功能,但没有包含在内。
See: https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (specifically "Elvis and other null safe operators").
The result is that this feature was considered for Java 7, but was not included.
正如很多答案提到的,Java 语言没有这个功能。
在少数情况下,使用这个编译器插件是可能的,有一些限制
在您提到的示例代码中可以是写为
PS:我是插件的作者
As lot of answers mentioned Java language don't have this feature.
It is possible in few scenarios with this compiler plugin, with few limitations
In the example code you mentioned can be written as
PS: I am author of plugin
可以定义 util 方法,使用 Java 8 lambda 以几乎漂亮的方式解决这个问题。
这是H-MAN 解决方案的变体< /a> 但它使用带有多个参数的重载方法来处理多个步骤,而不是捕获 NullPointerException。
即使我认为这个解决方案有点酷,我想我更喜欢 Helder Pereira 的 第二个,因为它不需要任何 util 方法。
It is possible to define util methods which solves this in an almost pretty way with Java 8 lambda.
This is a variation of H-MANs solution but it uses overloaded methods with multiple arguments to handle multiple steps instead of catching
NullPointerException
.Even if I think this solution is kind of cool I think I prefer Helder Pereira's seconds one since that doesn't require any util methods.
我不确定这是否有效;比如说,如果 person 引用为 null,运行时会用什么替换它?一个新人?这将要求 Person 具有您在本例中所期望的一些默认初始化。您可以避免空引用异常,但如果您没有计划这些类型的设置,您仍然会遇到不可预测的行为。
这 ?? C# 中的运算符最好称为“合并”运算符;您可以链接多个表达式,它将返回第一个不为空的表达式。不幸的是,Java 没有它。我认为您能做的最好的事情就是使用三元运算符执行空检查,并在链中的任何成员为空时评估整个表达式的替代方案:
您还可以使用 try-catch:
I'm not sure this would even work; if, say, the person reference was null, what would the runtime replace it with? A new Person? That would require the Person to have some default initialization that you'd expect in this case. You may avoid null reference exceptions but you'd still get unpredictable behavior if you didn't plan for these types of setups.
The ?? operator in C# might be best termed the "coalesce" operator; you can chain several expressions and it will return the first that isn't null. Unfortunately, Java doesn't have it. I think the best you could do is use the ternary operator to perform null checks and evaluate an alternative to the entire expression if any member in the chain is null:
You could also use try-catch:
现在您已经看到了 Java 8 中的 null 安全调用:
There you have it, null-safe invocation in Java 8:
如果有人正在寻找旧 java 版本的替代品,你可以尝试我写的这个:
If someone is looking for an alternative for old java versions, you can try this one I wrote:
你可以测试一下你提供的代码,它会给出语法错误。所以,Java不支持它。
Groovy 确实支持它,并且它是针对 Java 7 提出的(但从未被包含在内)。
但是,您可以使用 Java 8 中提供的Optional。这可能会帮助您实现类似的目标。
https://docs.oracle.com/javase/ 8/docs/api/java/util/Optional.html
http://www.oracle.com/technetwork/articles/ java/java8-Optional-2175753.html
Optional 示例代码
You can test the code which you have provided and it will give syntax error.So, it is not supported in Java.
Groovy does support it and it was proposed for Java 7 (but never got included).
However, you can use the Optional provided in Java 8. This might help you in achieving something on similar line.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Example Code for Optional
步骤 1:使用此通用方法。
STEP-2 下面是使用此方法的一个示例
完成!
STEP-1 : Use this generic method.
STEP-2 one example of usage of this method is below
Done !!
由于 Android 不支持 Lambda 函数,除非您安装的操作系统 >= 24,因此我们需要使用反射。
Since Android does not support Lambda Functions unless your installed OS is >= 24, we need to use reflection.
如果这对您来说不是性能问题,您可以编写
If this is not a performance issue for you, you can write
最初的想法来自groovy。它被提议作为 Java 7 项目 Coin 的一部分:https://wiki .openjdk.java.net/display/Coin/2009+Proposals+TOC(Elvis 和其他空安全运算符),但尚未被接受。
相关的 Elvis 运算符 ?: 被提议将
x ?: y
简写为x != null ? x : y
,当 x 是复杂表达式时特别有用。The original idea comes from groovy. It was proposed for Java 7 as part of Project Coin: https://wiki.openjdk.java.net/display/Coin/2009+Proposals+TOC (Elvis and Other Null-Safe Operators), but hasn't been accepted yet.
The related Elvis operator ?: was proposed to make
x ?: y
shorthand forx != null ? x : y
, especially useful when x is a complex expression.Java 中不存在这种语法,据我所知,它也不会包含在任何即将推出的版本中。
This syntax does not exist in Java, nor is it slated to be included in any of the upcoming versions that I know of.
[编辑]
经过进一步思考,我发现实际上仅使用标准 Java 8 类就可以实现相同的目的:
在这种情况下,甚至可以选择默认值(例如
"<没有名字>"
),通过将其作为orElse
的参数传递来代替null
。[原始答案]
解决缺少“?”的一种方法使用 Java 8 的操作符而不需要 try-catch 的开销(如上所述,这也可能隐藏源自其他地方的 NullPointerException )的方法是创建一个类,以 Java-8-Stream 样式“管道”方法。
然后,给定的示例将变为:
[EDIT]
Upon further thought, I figured out that it is actually possible to achieve the same only using standard Java 8 classes:
In this case, it is even possible to choose a default value (like
"<no first name>"
) instead ofnull
by passing it as parameter oforElse
.[Original Answer]
One way to workaround the lack of "?" operator using Java 8 without the overhead of try-catch (which could also hide a
NullPointerException
originated elsewhere, as mentioned) is to create a class to "pipe" methods in a Java-8-Stream style.Then, the given example would become: