为了账号安全,请及时绑定邮箱和手机立即绑定

StringUtils 与 != null

StringUtils 与 != null

茅侃侃 2021-09-12 16:43:39
我经常遇到非常不同的字符串验证,我们都知道有新的库,例如 StringUtils。有人可以解释为什么例如StringUtils.isNotBlank(paymentTerm)或多或少地优先于paymentTerm != null?
查看完整描述

3 回答

?
慕的地6264312

TA贡献1817条经验 获得超6个赞

我觉得这个问题的前提已经是错误的了。您不应该在大多数地方检查空字符串——事实上,我认为您应该null尽可能避免使用,尤其是当存在另一个非空标记值时。并且String已经有了一个很好的“空”值:空字符串 ( "")!

如果""并且" "需要折叠成相同的值,那么标准库中已经有一个非常好的方法:.trim(). 但是,.trim()作为 上的实例方法String,仅适用于非空字符串。这不一定是坏事!

如果null和对你来说""意味着不同的东西,那么我认为你的数据模型太复杂了,你应该使用其他一些包装类而不是String直接使用。如果null""意思相同,那么您应该选择其中之一,并始终如一地使用它。这可能意味着需要进行一些!= null检查,但是如果您发现自己在整个代码库中经常需要一个isNullOrEmptyisNotBlank辅助函数,我会说这是一种代码异味,您确实应该致力于修复底层数据模型问题,而不是担心小助手功能。

这意味着什么?在避免!= null陈述问题中,最高投票的答案指出,实际上只有两种值可以为 null:(1) null 是有效值,或 (2) null 不是有效值.

情况(2)不是很有趣。Null 不是有效值,因此我们不应该尝试处理它。如果有的话,我们只要遇到它就抛出一个异常。否则我们会忽略它,让NullPointerException事情“自然地”发生。它不应该为空,因此根据定义,找到空值是一种特殊情况。

如果 null有效值,则表示 null 具有语义含义。这很可能意味着某个值“不存在”或“无效”。这里有两种子情况:(1a) null 表示与空字符串相同的内容,或 (1b) 表示不同的内容。

如果您有案例 (1b),那么我认为您的域模型中需要一个新实体。例如,您可以创建一个类似的类PaymentTerm,它具有单独的.isValid().isPresent()方法,以及一个.asString()访问器来获取字符串值(如果存在)。(在很多可能的方式,使一个PaymentTerm类,有很多可能的权衡:点是不是你需要这种特殊形式,但你需要的东西多了原始String的东西,你可以挂方式关闭的,因为这个东西现在是你的领域模型中的一流实体。)

如果您有 case (1a),那么 null 和空字符串在语义上都意味着相同的事情。但是它们在语法上非常不同!空字符串已经有一个实例方法来检查它 ( .isEmpty()) 并且可以安全地存储、传递、与其他字符串进行比较等。

因此,情况 (1a) 有两种可能的解决方案:(1a.1) 传递 null 和空字符串,并且在任何地方都必须检查其中之一,或者 (1a.2) 尽快将空值标准化为空字符串,然后将 null 视为无效值,并在任何地方使用空字符串。根据您的输入格式,您甚至可以“免费”获得这种行为(例如,空文本框自然将空字符串作为值,而不是空值)。

我的论点是 case (1a.1) 是一种代码异味。与其同时传递 null 和空字符串,并经常检查两者(手动或使用类似isNullOrEmpty或的方法isNotBlank),您应该尝试进入 case (2) 或 case (1a.2)。

请注意,这其实答案意味着,两个 isNotBlank!= null是次优!在分解良好的代码库中,您应该努力避免这两种情况,但我倾向于认为您应该努力避免isNotBlank更多类似的情况。

也就是说,如何检查 null 或空字符串并不是非常重要。无论如何,JIT 几乎肯定会内联检查,并且在许多情况下,如果窥视孔优化器可以以另一种方式证明空安全,则会完全忽略它们。要考虑的更重要的事情是null您的程序中是否为有效值,如果是,则值为空在语义上意味着什么。


查看完整回答
反对 回复 2021-09-12
?
慕哥9229398

TA贡献1877条经验 获得超6个赞

你的问题是有道理的,但你问问题的方式可以更有礼貌。

答案是,这取决于。StringUtils 提供了很多不错的方法。isNotBlank() 检查空、空以及一个或多个空白,并且节省了一定量的手动检查。它还可以简化单元测试。另一方面,您的商店可能不想导入并依赖外部库。

一般来说,正确的方法,尤其是当你刚开始的时候,是一样的。礼貌地询问技术负责人的意见,然后接受。


查看完整回答
反对 回复 2021-09-12
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

paymentTerm != null并且StringUtils.isNotBlank(paymentTerm)不执行同样的事情。
如果你想检查的非无效String对象,你不想使用isNotBlank(),但使用!= null。所以使用!= null.
请注意,作为替代方案,您也可以使用,Object.nonNull(Object)但它通常更冗长(但在完全有意义的方法参考中:)Object::nonNull

关于我们是否应该测试!= ""!= trimmed ""或者只是之后!= null,这是一个需求问题。
即使isNotBlank()包含!= null,您也只会在需要时使用它,因为执行更多所需的检查会误导代码。


下面是一些简单的例子,你可以看到每种方式都有一个意义,你必须以一种让他们的阅读自然和愉快的方式使用它们(或不使用它们)。

1) 您要检查String长度尺寸。

if (myString != null && myString.length() == 8)

是你所需要的。
这样做很isNotBlank()冗长,传达了两个非常具体的东西(不是空白和最小长度),而只有最后一个很重要。

if (StringUtils.isNotBlank(myString) && myString.length() == 8)

2)您要检查String包含一些字符。

if (myString != null && myString.contains("word"))

仍然是您所需要的。

if (String.isNotBlank(myString) && myString.contains("word"))

这样做isNotBlank()似乎仍然是噪音。

3) 您想检查String等于另一个不能是null或它是编译时常量表达式的。

你想直接写:

if ("word".equals(myString))

4) 那么你想isNotBlank()什么时候使用?
只有当你需要检查一个String不为空,只有不包含空格(" ")字符。

if (StringUtils.isNotBlank("word"))


查看完整回答
反对 回复 2021-09-12
  • 3 回答
  • 0 关注
  • 149 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信