在字符串文字上调用equals

我只是整理了我的代码并且有这篇文章:

String saving = getValue(); if(saving != null && saving.equals("true")){ // do something } 

然后我想到了另一种方法来摆脱对null的检查:

 if("true".equals(saving)){ // do something } 

它确实有效,但这样是否安全 ? 我的意思是字符串文字存储在公共池中,而由new创建的字符串对象存储在堆上。 但是常量池中的字符串也是对象,对吧?

但即使它使代码更短,它似乎也不是正确的做法。

这是安全的 – 正如您所见,这是一种避免空指针的好方法。

你提到了使用new for Strings。 许多java静态代码分析工具将建议始终使用new String("foo");文字new String("foo");

编辑:

如果你想,你甚至可以使用:

 if (Boolean.valueOf(saving)) { ... } 

根据文档 ,传递null将返回false

为了确保对这个问题有一套完全平衡的答案,我想发表一个不同的意见。

我认为这种机制是愚蠢的。

如果你有一个null你应该知道它一旦发生 – 隐藏它只会推迟它的发现。 如果null不是例外,则将其替换为其他内容。

采用这种方法可以强化您的代码,使用所谓的防御性编程尽快发现您的错误而不是掩盖,直到一切都崩溃。

总之 – NullPointerException是你的朋友。 您应该使用它来查找代码中的错误。 一旦确定null不是exception, 就很容易使用Empty对象,例如Collections.emptySet()

使用Yoda技术的习惯将不可避免地隐藏你不想隐藏的错误。 使用它会更早地暴露错误。 对我而言,这是充分的论据,不使用它 – 永远。

给我 – 使用

 if(saving != null && saving.equals("true")){ 

意味着我实际上希望允许savingsnull ,这是一个可接受的情况 – 使用

 if("true".equals(saving)){ 

只是以一种可能成为坏习惯的方式隐藏那种刻意的选择。

它被称为yoda条件(在比较中将变量放在一个常量之前)可以被认为是不好的做法,也许对于那些可读性较差的人(比如我)。

但有时候使用yoda条件会使代码更“易于理解” ->你不需要在它前面加上额外的空值检查,它可以有效地区分代码块和强烈禁止null的情况。

我不同意一些答案。 有时您确实想知道您的变量是否为null 。 这可能表明您的代码中发生了一些不好的事情,您可能想重新考虑您的逻辑。

我不喜欢做if("someString".equals(myString)); 因为我确实想知道myString是否为null并且可能处理它或更改我的逻辑以防止这样的情况。

想象一下,由于某些错误,您有一个被错误计算的对象数组:

 myStrings = {..., ..., null, null, ...}; 

然后你想对数组的对象执行一些操作,你将拥有:

 if("myString".equals(myObjArray[i])) { ... } 

你不会得到NullPointerException ,你会认为你对数组中的所有对象都执行了操作。你永远不会知道你错误地计算了它,因为你“隐藏”了exception。 如果你做了:

 if(myObjArray[i].equals("myString")) { ... } 

你会得到一个NPE ,你会知道数组中有问题……你可能想要修复它或以另一种方式处理它。

 if("true".equals(saving)){ // do something } 

这是非常安全和良好的做法。 字符串“true”永远不会为null。 因此,您永远不会将String与null进行比较。 这段代码非常好

首先放置文字的格式避免了潜在的NPE,并且对于"literal".equals(null)将始终为false。

这是因为“literal”表达式总是求值为String对象(因此永远不为null), String.equals(obj)检查另一个对象是否为null(通过asinstanceof )。 对象一个对象 – 不需要担心“堆”。

在equals实现中使用null-guard是一种很好的做法,因为null.equals(null)是不允许的:“equals方法在非null对象引用上实现等价关系”

这是String.equals的源代码 (对于OpenJDK):

 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { // .. } return false; } 

对不起,我不能同意这个问题。

如果您首先使用常量,则支持可以掩盖编程错误的结构。 一个人应该只生成代码

  1. 添加function,
  2. 修复编程错误
  3. 或试图支持结构以避免编程错误(如设计模式)。

最重要的是,你对变量有一个弱的断言。 以下代码总是被强制检查空值。

如果您必须处理来自其他模块的空值,那么您的任务就是尽早将它们映射到域模型中的正确表示中。

在你自己的代码中,避免将null作为参数或返回值,因此不再需要任何空值检查,包括建议的代码片段。

你看,这个主题更多的是关于避免null而不是接受它来征服你的代码。

不仅安全,而且它也是解决这个问题的首选方式