我经常遇到非常不同的String验证,我们都知道有新的库,例如StringUtils。有人可以解释为什么StringUtils.isNotBlank(paymentTerm)
比paymentTerm != null
受到更多或更少的偏爱吗?
答案 0 :(得分:2)
我觉得这个问题的前提已经是一个不正确的问题。您不必在大多数地方检查空字符串-实际上,我认为您应该尽可能避免使用null
,而当存在另一个非空前哨值时,尤其是 。并且String
已经有一个很好的“空”值:空字符串(""
)!
如果需要将""
和" "
折叠成相同的值,那么标准库.trim()
中已经有一个非常好的方法。但是,.trim()
作为String
的实例方法,仅适用于非空字符串。这不一定是一件坏事!
如果null
和""
对您来说意味着不同的事情,那么我认为您的数据模型太复杂了,您应该使用其他包装类,而不是而不是直接使用String
。如果null
和""
含义相同,那么您应该选择一个或另一个,并始终使用它。这可能意味着需要进行几项!= null
检查,但是如果您发现自己在整个代码库中经常需要isNullOrEmpty
或isNotBlank
辅助函数,则请说那是代码的味道,您确实应该致力于解决潜在的数据模型问题,而不用担心很小的辅助函数。
那是什么意思?在Avoiding != null
statements问题中,投票最高的答案指出,实际上只有两种实例的值可以为null:(1)null是有效值,或者(2)null不是有效值。
案例(2)并不是很有趣。 Null不是有效值,因此我们不应该尝试处理它。如果有的话,如果遇到异常,我们只是抛出一个异常。否则,我们将忽略它,并让NullPointerException
“自然”发生。它不应该为null,因此按定义查找null是一种特殊情况。
如果null 是有效值,则表示null具有语义。最有可能意味着值“不存在”或“无效”。这里有两种情况:(1a)null表示与空字符串相同,或者(1b)表示不同。
如果您遇到案例(1b),那么我认为您需要在域模型中使用新实体。例如,您可以创建一个类似PaymentTerm
的类,该类具有单独的.isValid()
和.isPresent()
方法,以及一个.asString()
访问器来获取字符串值(如果存在)。 (创建PaymentTerm
类的很多可能方法,但有很多可能的折衷:并不是说您需要这种特定的形式,而是需要更多的 something 原始String
,您可以将其挂起方法,因为这已经成为您域模型中的一流实体。)
如果具有大小写(1a),则从语义上讲,null和空字符串都表示同一件事。但是它们在语法上有很大的不同!空字符串已经有一个实例方法来检查它(.isEmpty()
),并且可以安全地存储,传递,与其他字符串进行比较等等。
因此,情况(1a)有两种可能的解决方案:(1a.1)您同时传递null和空字符串,并且到处都需要检查其中一个,或者(1a.2)将null标准化为空字符串最快的机会,然后将null视为无效值,并在各处使用空字符串。根据您的输入格式,您甚至可以“免费”获得此行为(例如,一个空的文本框自然会将空字符串作为值,而不是null)。
我的论点是案例(1a.1)是一种代码气味。您应该尝试进入大小写(2)或大小写(),而不是同时传递null和空字符串,并经常检查它们(手动或使用isNullOrEmpty
或isNotBlank
之类的方法) 1a.2)。
请注意,此答案实际上意味着两者 isNotBlank
和!= null
都不是最佳选择!在结构良好的代码库中,您应该努力避免它们两者都出现,但是我倾向于认为您应该在工作时更加避免使用类似isNotBlank
之类的东西。
也就是说,如何检查空值或空字符串并不十分重要。 JIT几乎肯定会以任何方式内联检查,并且在许多情况下,如果窥孔优化器可以用另一种方式证明空安全性,它将完全消除它们。要考虑的更重要的事情是null
在您的程序中是否为有效值,如果是,则在语义上将值
答案 1 :(得分:0)
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"))
答案 2 :(得分:0)
您的问题是有效的,但您可能会问得更礼貌。
答案是,这取决于。 StringUtils提供了许多不错的方法。 isNotBlank()检查null,empty和一个或多个空格,并节省一定数量的手动检查。它还可以简化单元测试。另一方面,您的商店可能不想导入并依赖外部库。
通常,正确的方法(尤其是刚入门时)是相同的方法。礼貌地向技术负责人征询他们的意见,然后接受。