将字符串与空字符串进行比较(Java)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/531779/
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
Comparing a string with the empty string (Java)
提问by user42155
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:
我有一个关于将字符串与 Java 中的空字符串进行比较的问题。是否有差异,如果我比较与空字符串的字符串==
或equals
?例如:
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.
我知道应该将字符串(以及一般的对象)与equals
, 而不是 进行比较==
,但我想知道这对空字符串是否重要。
回答by tddmonkey
It's going to depend on if the string is a literal or not. If you create the string with
这将取决于字符串是否为文字。如果您创建字符串
new String("")
Then it will never match "" with the equals operator, as shown below:
那么它将永远不会匹配“”与等于运算符,如下所示:
String one = "";
String two = new String("");
System.out.println("one == \"\": " + (one == ""));
System.out.println("one.equals(\"\"): " + one.equals(""));
System.out.println("two == \"\": " + (two == ""));
System.out.println("two.equals(\"\"): " + two.equals(""));
--
——
one == "": true
one.equals(""): true
two == "": false
two.equals(""): true
Basically, you want to always use equals()
基本上,你想总是使用 equals()
回答by Rob
A string, is a string, is a string, whether it's the empty string or not. Use equals()
.
一个字符串,就是一个字符串,就是一个字符串,不管它是不是空字符串。使用equals()
.
回答by cletus
s1 == ""
is not reliable as it tests reference equality not object equality (and String isn't strictly canonical).
不可靠,因为它测试引用相等而不是对象相等(并且 String 不是严格规范的)。
s1.equals("")
is better but can suffer from null pointer exceptions. Better yet is:
更好,但可能会受到空指针异常的影响。更好的是:
"".equals(s1)
No null pointer exceptions.
没有空指针异常。
EDIT:Ok, the point was asked about canonical form. This article defines it as:
编辑:好的,这一点被问及规范形式。本文将其定义为:
Suppose we have some set S of objects, with an equivalence relation. A canonical form is given by designating some objects of S to be "in canonical form", such that every object under consideration is equivalent to exactly one object in canonical form.
假设我们有一些具有等价关系的对象集合 S。规范形式是通过将 S 的某些对象指定为“规范形式”来给出的,这样所考虑的每个对象都恰好等同于规范形式的一个对象。
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
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 formof this set of rational numbers.
有理数通常被写成 gcd(最大公约数)为 1。所以它们都将被简化为 3/2。3/2 可以被视为这组有理数的规范形式。
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:
那么在编程中使用术语“规范形式”意味着什么?它可能意味着几件事。以这个虚构的类为例:
public class MyInt {
private final int number;
public MyInt(int number) { this.number = number; }
public int hashCode() { return number; }
}
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:
MyInt 类的哈希码是该类的规范形式,因为对于 MyInt 的所有实例的集合,您可以采用任意两个元素 m1 和 m2,它们将遵循以下关系:
m1.equals(m2) == (m1.hashCode() == m2.hashCode())
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:
这种关系是规范形式的本质。出现这种情况的一种更常见的方式是在类上使用工厂方法,例如:
public class MyClass {
private MyClass() { }
public MyClass getInstance(...) { ... }
}
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:
实例不能直接实例化,因为构造函数是私有的。这只是一个工厂方法。工厂方法允许你做的是这样的事情:
- Always return the same instance (abstracted singleton);
- Just create a new intsance with every call;
- Return objects in canonical form(more on this in a second); or
- whatever you 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:
你可以用这个工厂方法做的是缓存你创建的实例,这样对于任何两个实例 s1 和 s2 它们都遵守以下测试:
(s1 == s2) == s1.equals(s2)
So when I say String isn't strictly canonical it means that:
因此,当我说 String 并非严格规范时,它意味着:
String s1 = "blah";
String s2 = "blah";
System.out.println(s1 == s2); // true
But as others have poitned out you can change this by using:
但正如其他人指出的那样,您可以使用以下方法来改变这一点:
String s3 = new String("blah");
and possibly:
并且可能:
String s4 = String.intern("blah");
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.
作为对上述模式的警告,我应该指出,由于序列化,使用私有构造函数和工厂方法控制对象创建并不能保证引用相等意味着对象相等。序列化绕过了正常的对象创建机制。Josh Bloch 在 Effective Java(最初在第一版中谈到了后来成为 Java 5 中的语言特性的类型安全枚举模式时)讨论了这个主题,您可以通过重载(私有)readResolve() 方法来解决这个问题。但这很棘手。类加载器也会影响这个问题。
Anyway, that's canonical form.
无论如何,这是规范形式。
回答by Raibaz
"".equals(s)
Seems to be the best option, but there is also Stringutils.isEmpty(s)
contained in the Apache commons lang library
似乎是最好的选择,但也Stringutils.isEmpty(s)
包含在 Apache commons lang 库中
回答by eaolson
It's a bit sideways from your original question, but there's always
与您最初的问题有点不同,但总是有
if(s1.length() == 0)
I believe this is equivalent to isEmpty() method from 1.6.
我相信这相当于 1.6 中的 isEmpty() 方法。
回答by Jared
Given two strings:
给定两个字符串:
String s1 = "abc";
String s2 = "abc";
-or -
-或者 -
String s1 = new String("abc");
String s2 = new String("abc");
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.
对两个对象执行的 == 运算符检查对象身份(如果两个运算符返回到同一个对象实例,则返回 true。)应用于 java.lang.Strings 的 == 的实际行为并不总是看起来一致,因为字符串实习。
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.
在 Java 中,字符串被实习(至少部分由 JVM 自行决定)。在任何时候,s1 和 s2 可能会或可能不会被实习为相同的对象引用(假设它们具有相同的值。)因此s1 == s2
可能会也可能不会返回 true,这完全取决于 s1 和 s2 是否都被实习。
Making s1 and s2 equal to empty Strings has no effect on this - they still may or may not have been interned.
使 s1 和 s2 等于空字符串对此没有影响 - 它们仍然可能或可能没有被实习。
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.
简而言之,如果 s1 和 s2 具有相同的内容,== 可能会也可能不会返回 true。如果 s1 和 s2 具有相同的内容,则 s1.equals(s2) 保证返回 true。
回答by matsev
Use String.isEmpty(), or StringUtils.isEmpty(String str)if you need a null check.
如果需要空检查,请使用String.isEmpty()或StringUtils.isEmpty(String str)。
回答by Linuslabo
Short answer
简答
s1 == "" // No!
s1.equals("") // Ok
s1.isEmpty() // Ok: fast (from Java 1.6)
"".equals(s1) // Ok: null safe
I would assure s1 is not null and use isEmpty().
我会保证 s1 不为空并使用 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 对象的引用取决于它们的创建方式:
String objects created using the operator newalways refer to separate objects, even if they store the same sequence of characters so:
使用运算符new创建的字符串对象始终引用单独的对象,即使它们存储相同的字符序列,因此:
String s1 = new String("");
String s2 = new String("");
s1 == s2 // false
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.
使用运算符 = 创建的字符串对象后跟一个用双引号括起来的值 ( = "value") 存储在 String 对象池中:在池中创建新对象之前,在池中搜索具有相同值的对象并在找到时引用。
String s1 = ""; // "" added to the pool
String s2 = ""; // found "" in the pool, s2 will reference the same object of s1
s1 == s2 // true
The same is true for strings created enclosing a value whitin double quotes ("value"), so:
对于用双引号(“value”)括起来的值创建的字符串也是如此:
String s1 = "";
s1 == ""; //true
String equals method checks for both, that's why it is safe to write:
String equals 方法检查两者,这就是为什么写是安全的:
s1.equals("");
This expression may throw a NullPointerException if s1 == null, so, if you don't check for null before, it is safer to write:
如果 s1 == null,此表达式可能会抛出 NullPointerException,因此,如果您之前不检查 null,则更安全的写法是:
"".equals(s1);
Please read also How do I compare strings in Java?
另请阅读如何比较 Java 中的字符串?
Hope it may help not so experienced users, who may find other answers a bit too complicated. :)
希望它可以帮助没有经验的用户,他们可能会发现其他答案有点过于复杂。:)