Java 在字符串文字上调用 equals
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20385179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling equals on string literal
提问by Kuba Spatny
I just was tidying my code a bit and there was this piece:
我只是在整理一下我的代码,然后有一段:
String saving = getValue();
if(saving != null && saving.equals("true")){
// do something
}
Then I thought of doing it the other way around to get rid of the checking for null
:
然后我想反过来做,以摆脱对以下内容的检查null
:
if("true".equals(saving)){
// do something
}
It definitely works, but is this safeto do so? I mean string literals are stored in a common pool, while string object create by new
are on the heap. But strings in the constant pool are also objects, right?
它绝对有效,但是这样做安全吗?我的意思是字符串文字存储在一个公共池中,而创建的字符串对象new
在堆上。但是常量池中的字符串也是对象吧?
But still it doesn't seem like the right thing to do, even though it makes the code shorter.
但它似乎仍然不是正确的做法,即使它使代码更短。
采纳答案by jakson
This is safe - and as you have seen, a good way of avoiding null pointers.
这是安全的 - 正如您所见,这是避免空指针的好方法。
You mention the use of new
for Strings. Many java static code analysis tools will recommend always using literals over new String("foo");
.
您提到了new
for 字符串的使用。许多 java 静态代码分析工具会建议始终使用文字而不是new String("foo");
.
Edit:
编辑:
If you wanted, you could even just use:
如果你愿意,你甚至可以使用:
if (Boolean.valueOf(saving)) {
...
}
According to the docs, passing null
will return false
.
根据文档,传递null
将返回false
。
回答by Simon Dorociak
It's called yoda conditions (putting a constant before a variable in a comparison) can be considered like bad practise, maybe for someone much less readable (like me).
它被称为 yoda 条件(在比较中在变量之前放置一个常量)可以被认为是不好的做法,也许对于不太可读的人(比如我)。
But sometimes using yoda condition makes the code more "comprehensible" ->
you don't need to put extra null check in front of it and it efficiently differentiates block of code from case where null is strongly forbidden.
但有时使用 yoda 条件会使代码更“易于理解”,->
您不需要在它前面放置额外的空检查,它有效地将代码块与强烈禁止空的情况区分开来。
回答by user2864740
The format of putting the literal first avoids the potential NPE and will always be false for "literal".equals(null)
.
将文字放在首位的格式避免了潜在的 NPE,并且对于"literal".equals(null)
.
This is because a "literal" expression alwaysevaluates to a String object (and is thus never null) and String.equals(obj)
checks to see if the otherobject is a null (via asinstanceof
). An object isan object - no need to worry bout the "heap".
这是因为“文字”表达式始终计算为 String 对象(因此永远不会为空)并String.equals(obj)
检查另一个对象是否为空(通过asinstanceof
)。对象就是对象 - 无需担心“堆”。
It's good practice to have a null-guard in an equals implementationas null.equals(null)
is notpermissible: "The equals method implements an equivalence relation on non-nullobject references"
这是很好的做法,对空后卫等号实现为null.equals(null)
是不容许的道:“equals方法实现一个等价关系的非空对象引用”
Here is the String.equals the source(for OpenJDK):
这是String.equals 的源代码(对于 OpenJDK):
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
// ..
}
return false;
}
回答by k4sia
if("true".equals(saving)){
// do something
}
This is very safe and good practice. String "true" will never be null. So you will never compare your String to null. This piece of code is perfectly fine
这是非常安全和良好的做法。字符串“true”永远不会为空。所以你永远不会将你的字符串与空值进行比较。这段代码完全没问题
回答by OldCurmudgeon
Just to ensure there is a fully balanced set of answers to this question I would like to post a different opinion.
为了确保对这个问题有一套完全平衡的答案,我想发表不同的意见。
I think this mechanism is foolish.
我认为这种机制是愚蠢的。
If you have a null
you should know as soon as it happens - hiding it will just postpone its discovery. If the null
is not an exception, replace it with something else.
如果你有一个null
你应该在它发生时尽快知道 - 隐藏它只会推迟它的发现。如果null
不是例外,请用其他东西替换它。
Taking this approach will fortify your code with what is called defensive programmingwhere your mistakes are discovered as soon as possiblerather than covered up until everything falls apart.
采用这种方法将通过所谓的防御性编程来强化您的代码,在这种情况下,您的错误会尽快被发现,而不是被掩盖,直到一切都崩溃为止。
In summary - NullPointerException
is your friend. You should use it to find mistakes in your code. It is veryeasy to use a Emptyobject such as Collections.emptySet()
once you have determined that the null
is not an exception.
总之-NullPointerException
是你的朋友。您应该使用它来查找代码中的错误。这是很容易使用一个空的对象,如Collections.emptySet()
一旦你已经确定,null
也不例外。
Using the Yoda technique out of habit will inevitably hide errors you do not mean to hide. Notusing it will expose errors much earlier. To me that is sufficient argument to not use it - ever.
出于习惯使用尤达技巧将不可避免地隐藏您不想隐藏的错误。不使用它会更早地暴露错误。对我来说,这是不使用它的充分理由 - 永远。
To me - using
对我来说 - 使用
if(saving != null && saving.equals("true")){
means that I actually want to allow savings
to be null
and it is an acceptable situation - using
意味着其实我是想允许savings
是null
,它是一个可以接受的情况-使用
if("true".equals(saving)){
merely hides that deliberate choice in a way that could become a bad habit.
只是以一种可能成为坏习惯的方式隐藏了这种刻意的选择。
回答by Maroun
I disagree with some of the answers. Sometimes you dowant to know if your variable is null
. It might be an indication that something is bad happening in your code and you might want to reconsider your logic.
我不同意某些答案。有时您确实想知道您的变量是否为null
. 这可能表明您的代码中发生了一些不好的事情,您可能需要重新考虑您的逻辑。
I don't like to do if("someString".equals(myString));
because I dowant to know if myString
is null
and maybe handle it or change my logic to prevent situations like this.
我不喜欢这样做,if("someString".equals(myString));
因为我确实想知道是否myString
是null
并且可能会处理它或更改我的逻辑以防止出现此类情况。
Imagine you have an array of Objects that was miscalculated due to some bug:
想象一下,由于某些错误,您有一组对象计算错误:
myStrings = {..., ..., null, null, ...};
Then you want to perform some operations on the objectsof the array, and you'll have:
然后你想对数组的对象执行一些操作,你将有:
if("myString".equals(myObjArray[i])) { ... }
You won't get NullPointerException
and you'll think that you performed the operation on all the objectsin the array.. And you'll never know that you miscalculated it because you "hided" the exception. Whereas if you did:
你不会得到NullPointerException
,你会认为你对数组中的所有对象执行了操作..你永远不会知道你错误计算了它,因为你“隐藏”了异常。而如果你这样做:
if(myObjArray[i].equals("myString")) { ... }
You'll get a NPEand you'll know something is wrong in the array.. and you might want to fix this or handle it in another way.
你会得到一个NPE,你会知道数组中有问题......你可能想要修复这个问题或以其他方式处理它。
回答by oopexpert
Sorry but I cannot agree on that issue.
抱歉,我不能同意这个问题。
If you use the constant first you support structures that veil programming errors. And one should only produce code either
如果您首先使用常量,则您支持掩盖编程错误的结构。一个人应该只生成代码
- to add functionality,
- fix an programming error
- or trying to support structures to avoid programming errors (like design patterns).
- 添加功能,
- 修复编程错误
- 或尝试支持结构以避免编程错误(如设计模式)。
On top you have a weak assertion about the variable. Following code is always forced to check for null values as well.
最重要的是,您对变量有一个弱断言。以下代码也总是被迫检查空值。
If you have to deal with null values from other modules your task is to map them into proper representations in your domain model as early as possible.
如果您必须处理来自其他模块的空值,您的任务是尽早将它们映射到域模型中的正确表示中。
In your own code avoid null as parameter or return value, so there won't be any null-checks neccessary anymore, the suggested piece of code included.
在您自己的代码中,避免将 null 作为参数或返回值,因此不再需要任何 null 检查,包括建议的代码段。
You see, this subject is more about avoiding null than accepting it to conquer your code.
你看,这个主题更多的是关于避免 null 而不是接受它来征服你的代码。
回答by schlebe
if ("true".equals(saving))
is perfectly "save" and recommended by dummy product as SonarLint and any other advisors that establish this "well" thinked rule that your chief request that you follow.
完美地“保存”并被虚拟产品推荐为 SonarLint 和任何其他建立此“深思熟虑”规则的顾问,您的首席要求您遵循。
I say stupid and my explanation is the following.
我说愚蠢,我的解释如下。
What happens if you have following code
如果您有以下代码会发生什么
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
You can use following advised code
您可以使用以下建议的代码
if (!"true".equals(saving))
{
if (saving.length() > 10)
{
// do something
}
}
But when your code is deployed on production, the program will crash on length()
function if saving variable has not been initialized and contains NULL.
但是当你的代码被部署到生产中时,length()
如果保存变量没有被初始化并且包含 NULL ,程序将会在函数上崩溃。
You have changing your code to avoid NullPointerException
on equals()
function but your program will return another NullPointerException
on length()
function !
你已经改变你的代码,以避免NullPointerException
在equals()
功能,但你的程序将返回另一个NullPointerException
上length()
的功能!
The good reaction is to stop to use String literal tip and to analyze code to find a perfect solution as in the following example.
好的反应是停止使用 String 文字提示并分析代码以找到一个完美的解决方案,如下例所示。
if (saving != null)
{
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
}
or
或者
if (saving == null) saving = "";
if (!saving.equals("true"))
{
if (saving.length() > 10)
{
// do something
}
}
Is is perhaps verbose but if you will use Java for programming it is the price to pay.
Is 可能是冗长的,但如果您将使用 Java 进行编程,这是要付出的代价。
Using String literal equals() method to avoid NullPointerException
has the following disadvantages
使用Stringliteralequals()方法来避免NullPointerException
有以下缺点
- the solution is tricky
- the code is not naturally readable for human
- equality will not crash but another part of program will continue to crash
- code become quickly difficult to read if this tips is used for lower() and greater() functions (example: if ('USA'.greater(sCode)))
- give a false impression that the code is safe
- 解决方案很棘手
- 代码对于人类来说不是自然可读的
- 平等不会崩溃,但程序的另一部分将继续崩溃
- 如果将此提示用于lower() 和greater() 函数,代码将很快变得难以阅读(例如:if ('USA'.greater(sCode)))
- 给人一种代码安全的错误印象