比较字符串与空字符串 (Java)
我有一个关于在 Java 中比较字符串和空字符串的问题。 如果我使用 ==
或 equals
比较字符串与空字符串,有什么区别吗? 例如:
String s1 = "hi";
if (s1 == "")
或者
if (s1.equals(""))
我知道应该将字符串(以及一般对象)与 equals
进行比较,而不是 ==
,但我想知道这对于空字符串是否重要。
I have a question about comparing a string with the empty string in Java. Is there a difference, if I compare a string with the empty string with ==
or equals
? For example:
String s1 = "hi";
if (s1 == "")
or
if (s1.equals(""))
I know that one should compare strings (and objects in general) with equals
, and not ==
, but I am wondering whether it matters for the empty string.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
不可靠,因为它测试引用相等性而不是对象相等性(并且 String 不是严格规范的)。
更好,但可能会出现空指针异常。 更好的是:
没有空指针异常。
编辑:好的,问题是关于规范形式。 本文将其定义为:
给你一个实际的例子:采用一组有理数(或通常称为“分数”)。 有理数由分子和分母(除数)组成,两者都是整数。 这些有理数是等价的:
3/2、6/4、24/16
有理数通常被写为 gcd(最大公约数)为 1。因此所有有理数都将被简化为 3/2。 3/2 可以被视为这组有理数的规范形式。
那么,当使用术语“规范形式”时,它在编程中意味着什么? 它可能意味着几件事。 以这个虚构的类为例:
类 MyInt 的哈希码是该类的规范形式,因为对于 MyInt 的所有实例的集合,您可以采用任意两个元素 m1 和 m2,它们将遵循以下关系
:是规范形式的本质。 出现这种情况的一种更常见的方式是当您在类上使用工厂方法时,例如:
实例无法直接实例化,因为构造函数是私有的。 这只是一个工厂方法。 工厂方法允许您执行以下操作:
基本上,工厂方法抽象了对象创建,我个人认为强制所有构造函数都是私有的以强制使用此模式将是一个有趣的语言功能,但我离题了。
您可以使用此工厂方法做的是缓存您创建的实例,以便对于任何两个实例 s1 和 s2,它们都遵守以下测试:
因此,当我说 String 不是严格规范的时,这意味着:
但正如其他人指出的那样您可以通过使用:
和可能的:
来更改此设置,因此您不能完全依赖引用相等性,因此您根本不应该依赖它。
作为对上述模式的警告,我应该指出,使用私有构造函数和工厂方法控制对象创建并不能保证引用相等意味着由于序列化而导致对象相等。 序列化绕过了正常的对象创建机制。 Josh Bloch 在《Effective Java》中介绍了这个主题(最初在第一版中,他谈到了类型安全枚举模式,后来成为 Java 5 中的一个语言特性),您可以通过重载(私有)readResolve() 方法来绕过它。 但这很棘手。 类加载器也会影响这个问题。
无论如何,这是规范的形式。
is not reliable as it tests reference equality not object equality (and String isn't strictly canonical).
is better but can suffer from null pointer exceptions. Better yet is:
No null pointer exceptions.
EDIT: Ok, the point was asked about canonical form. This article defines it as:
To give you a practical example: take the set of rational numbers (or "fractions" are they're commonly called). A rational number consists of a numerator and a denomoinator (divisor), both of which are integers. These rational numbers are equivalent:
3/2, 6/4, 24/16
Rational nubmers are typically written such that the gcd (greatest common divisor) is 1. So all of them will be simplified to 3/2. 3/2 can be viewed as the canonical form of this set of rational numbers.
So what does it mean in programming when the term "canonical form" is used? It can mean a couple of things. Take for example this imaginary class:
The hash code of the class MyInt is a canonical form of that class because for the set of all instances of MyInt, you can take any two elements m1 and m2 and they will obey the following relation:
That relation is the essence of canonical form. A more common way this crops up is when you use factory methods on classes such as:
Instances cannot be directly instantiated because the constructor is private. This is just a factory method. What a factory method allows you to do is things like:
Basically the factory method abstracts object creation and personally I think it would be an interesting language feature to force all constructors to be private to enforce the use of this pattern but I digress.
What you can do with this factory method is cache your instances that you create such that for any two instances s1 and s2 they obey the following test:
So when I say String isn't strictly canonical it means that:
But as others have poitned out you can change this by using:
and possibly:
So you can't rely on reference equality completely so you shouldn't rely on it at all.
As a caveat to the above pattern, I should point out that controlling object creation with private constructors and factory methods doesn't guarantee reference equality means object equality because of serialization. Serialization bypasses the normal object creation mechanism. Josh Bloch covers this topic in Effective Java (originally in the first edition when he talked about the typesafe enum pattern which later became a language feature in Java 5) and you can get around it by overloading the (private) readResolve() method. But it's tricky. Class loaders will affect the issue too.
Anyway, that's canonical form.
这将取决于字符串是否是文字。 如果您使用 Then 创建字符串
,它将永远不会与 equals 运算符匹配“”,如下所示:
--
基本上,您希望始终使用 equals()
It's going to depend on if the string is a literal or not. If you create the string with
Then it will never match "" with the equals operator, as shown below:
--
Basically, you want to always use equals()
简短回答
我保证 s1 不为 null 并使用 isEmpty()。
注意:空字符串“”不是特殊的字符串,而是与任何其他“值”一样计数。
更长一点的答案
对 String 对象的引用取决于它们的创建方式:
使用运算符 new 创建的 String 对象始终引用单独的对象,即使它们存储相同的序列字符数如下:
使用运算符 = 后跟用双引号括起来的值 (= "value") 创建的 String 对象存储在 String 对象池中:在池中创建新对象之前,在池中搜索具有相同值的对象,如果找到则引用。
对于用双引号(“value”)创建的值的字符串也是如此,因此:
String equals 方法检查两者,这就是为什么可以安全地编写:
如果 s1 == null,则此表达式可能会抛出 NullPointerException,因此,如果您之前不检查 null,则编写更安全:
另请阅读 如何在Java中比较字符串?
希望它可以帮助经验不足的用户,他们可能会发现其他答案有点太复杂。 :)
Short answer
I would assure s1 is not null and use isEmpty().
Note: empty string "" is not a special String, but counts as any other "value".
A little longer answer
References to String objects depend on the way they are created:
String objects created using the operator new always refer to separate objects, even if they store the same sequence of characters so:
String objects created using the operator = followed by a value enclosed whitin double quotes (= "value") are stored in a pool of String objects: before creating a new object in the pool, an object with the same value is searched in the pool and referenced if found.
The same is true for strings created enclosing a value whitin double quotes ("value"), so:
String equals method checks for both, that's why it is safe to write:
This expression may throw a NullPointerException if s1 == null, so, if you don't check for null before, it is safer to write:
Please read also How do I compare strings in Java?
Hope it may help not so experienced users, who may find other answers a bit too complicated. :)
这与你原来的问题有点偏离,但我总是
相信这相当于 1.6 中的 isEmpty() 方法。
It's a bit sideways from your original question, but there's always
I believe this is equivalent to isEmpty() method from 1.6.
似乎是最好的选择,但 Apache commons lang 库中还包含
Stringutils.isEmpty(s)
Seems to be the best option, but there is also
Stringutils.isEmpty(s)
contained in the Apache commons lang library字符串,是字符串,是字符串,无论是否为空字符串。 使用
equals()
。A string, is a string, is a string, whether it's the empty string or not. Use
equals()
.使用 String.isEmpty()< /a> 或 StringUtils.isEmpty(String str) 如果您需要空检查。
Use String.isEmpty(), or StringUtils.isEmpty(String str) if you need a null check.
给定两个字符串:
- 或 -
对两个对象执行的 == 运算符检查对象身份(如果两个运算符返回到同一个对象实例,则返回 true。)应用于 java.lang.Strings 的 == 的实际行为并不由于字符串驻留,看起来总是一致的。
在 Java 中,字符串interned(至少部分由 JVM 决定。)在某个时间点,s1 和 s2 可能会或可能不会被保留为相同的对象引用(假设它们具有相同的值)。因此
s1 == s2
可能会或可能不会返回 true,仅基于关于s1和s2是否都被拘留。使 s1 和 s2 等于空字符串对此没有影响 - 它们仍然可能已被保留,也可能没有被保留。
简而言之,如果 s1 和 s2 具有相同的内容,== 可能返回 true,也可能不返回 true。 如果 s1 和 s2 具有相同的内容,则 s1.equals(s2) 保证返回 true。
Given two strings:
-or -
The == operator performed on two Objects checks for object identity (it returns true if the two operators return to the same object instance.) The actual behavior of == applied to java.lang.Strings does not always appear to be consistent because of String interning.
In Java, Strings are interned (at least partly at the discretion of the JVM.) At any point in time, s1 and s2 may or may not have been interned to be the same object reference (supposing they have the same value.) Thus
s1 == s2
may or may not return true, based solely on whether s1 and s2 have both been interned.Making s1 and s2 equal to empty Strings has no effect on this - they still may or may not have been interned.
In short, == may or may not return true if s1 and s2 have the same contents. s1.equals(s2) is guaranteed to return true if s1 and s2 have the same contents.
通过使用isEquals()方法来比较空字符串和String。
通过使用另一种方法CompareTo()方法。
By using isEquals() method to compare with the empty string and String.
By using another method CompareTo() method.