英文:
Issue with Objects.nonNull() behavior
问题
使用Java 11。注意到一个非常简单功能的奇怪行为。在下面的代码中,如果过期日期不为null,那么它应该尝试从给定的Instant字段中提取sql.Timestamp
。
preparedStatement.setTimestamp(expirationDateParameterIndex,
Objects.nonNull(memberReward.getExpirationDate())
? Timestamp.from(memberReward.getExpirationDate())
: null);
问题是,即使将过期日期设置为null
,Timestamp.from(..)
仍然被调用,并抛出NullPointerException
。
java.lang.NullPointerException: null
at java.sql/java.sql.Timestamp.from(Timestamp.java:545)
这个问题在项目外部无法重现。
以下是调试截图:
英文:
Using Java 11. Noticing a strange behavior with very simple functionality. In the following code, if the expiration date is not null, only then it should try to extract the sql.Timestamp
from the given Instant
field.
preparedStatement.setTimestamp(expirationDateParameterIndex,
Objects.nonNull(memberReward.getExpirationDate())
? Timestamp.from(memberReward.getExpirationDate())
: null);
Problem is that even though the expiration date is set to null
, Timestamp.from(..)
is called and throwing NullPointerException
.
java.lang.NullPointerException: null
at java.sql/java.sql.Timestamp.from(Timestamp.java:545)
The issue is not reproducible outside the project.
Here are the debugging screenshots:
答案1
得分: 4
好的,以下是您要翻译的内容:
很好,您的调试截图很清楚:null
被传递到了 Timestamp.from()
,这意味着 memberReward.getExpirationDate()
为空。
这很奇怪,因为就在那之前,您检查了这个条件!因此,我们得出了以下几种相当奇特的解释:
getExpirationDate()
不稳定:它每次返回不同的值。想象一下,它的实现方式是这样的:return random.coinFlip() == HEADS ? null : someDateObj;
- 那么就有可能发生这种情况。解决这个问题的一种方法是调用它一次,将其保存在一个局部变量中,然后继续使用这个变量。- expirationDate 不是不可变的,在您的检查和读取之间,其他一些线程正在设置该值。虽然可能性很小,但在技术上是可能的,这意味着您需要认真地重新编写整个代码,因为在线程之间有这样随意的共享可变状态,意味着这只是众多竞态条件中的一种。
- 您看到的代码不是正在运行的代码。
- 您是从与您粘贴的代码不同的代码中进入到
Timestamp.from
的。 - 那不是
java.util
中的 Objects,以及它上面的 nonNull 方法,可能有问题。
这些都听起来很奇特,但肯定是其中的一种情况。
英文:
Well, your debug screenshot is clear: null
was passed to Timestamp.from()
, which means memberReward.getExpirationDate()
is null.
That's weird, because right before that, you check for that condition! Thus, we get to these explanations, all quite exotic:
getExpirationDate()
is non-stable: It returns different values every time. Imagine it was implemented as follows:return random.coinFlip() == HEADS ? null : someDateObj;
- then this can happen. One way to fix this is to call it once, save to a local variable, and carry on with that.- expirationDate is not immutable, and some other thread is setting the value in between your check and your read. This is unlikely, but technically possible, and suggests you need a serious rewrite of it all, having such casual shared mutable state between threads means this is just one of a ton of race conditions.
- The code you're seeing is not the code that is running.
- You're getting to Timestamp.from from different code than what you pasted.
- That is not the Objects of
java.util
, and the nonNull method on it, is broken.
These all sound exotic, but it must be one of these things.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论