将字符串与空字符串进行比较(Java)

     2023-02-16     152

关键词:

【中文标题】将字符串与空字符串进行比较(Java)【英文标题】:Comparing a string with the empty string (Java) 【发布时间】:2010-10-06 14:48:01 【问题描述】:

我有一个关于将字符串与 Java 中的空字符串进行比较的问题。如果我将字符串与空字符串与==equals 进行比较,是否有区别?例如:

String s1 = "hi";

if (s1 == "")

if (s1.equals("")) 

我知道应该将字符串(和一般的对象)与equals 进行比较,而不是==,但我想知道它对于空字符串是否重要。

【问题讨论】:

比较长度不是更好吗?我觉得长度比较比字符串比较更优化 @Ravisha 在内部,String.java'sequals 方法有几个优化:1:参考==比较,2:instanceof String在转换之前检查,并在最后逐字符比较字符串之前比较 3: 长度值。所以回答你的问题,是的,长度比较是有效的,但你的代码应该依赖 String.equals 而不是重新发明它的任何***。 @Patrick M 。如果这里的目的是检查空字符串,我更喜欢比较长度。而不是比较。 @Ravisha 我同意你的观点。问题及其答案最终集中在字符串比较的规范形式上,当其中一个字符串可能为空时,它具有特定的“正确”方式。但是从检测字符串是否为空的更广泛的角度来看,有专门定义的.isEmpty() 方法“当且仅当length() 为0 时返回true”。但是你仍然需要做一个空检查,这就是为什么我更喜欢 C# 的public static bool IsNullOrEmpty 【参考方案1】:

这将取决于字符串是否为文字。如果您使用

创建字符串
new String("")

那么它永远不会用等号匹配“”,如下所示:

    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

基本上,您希望始终使用 equals()

【讨论】:

【参考方案2】:

字符串,是字符串,是字符串,不管是不是空字符串。使用equals()

【讨论】:

【参考方案3】:
s1 == ""

不可靠,因为它测试引用相等而不是对象相等(并且 String 不是严格规范的)。

s1.equals("")

更好,但可能会遇到空指针异常。更好的是:

"".equals(s1)

没有空指针异常。

编辑:好的,问题是关于canonical form。本文将其定义为:

假设我们有一些对象集合 S, 具有等价关系。一种 规范形式是通过指定 S的一些对象是“在规范中 形式”,这样每个对象下 考虑完全等同于 一个规范形式的对象。

举一个实际的例子:取一组有理数(或“分数”,它们通常被称为)。有理数由分子和分母(除数)组成,两者都是整数。这些有理数是等价的:

3/2、6/4、24/16

有理数的写法通常使 gcd(最大公约数)为 1。因此,它们都将简化为 3/2。 3/2 可以看作是这组有理数的规范形式

那么在编程中使用术语“规范形式”意味着什么?这可能意味着几件事。以这个虚构的类为例:

public class MyInt 
  private final int number;

  public MyInt(int number)  this.number = number; 
  public int hashCode()  return number; 

类 MyInt 的哈希码是该类的规范形式,因为对于 MyInt 的所有实例的集合,您可以取任意两个元素 m1 和 m2,它们将遵循以下关系:

m1.equals(m2) == (m1.hashCode() == m2.hashCode())

这种关系是规范形式的本质。出现这种情况的一种更常见的方式是当您在类上使用工厂方法时,例如:

public class MyClass 
  private MyClass()  

  public MyClass getInstance(...)  ... 

实例不能直接实例化,因为构造函数是私有的。这只是一种工厂方法。工厂方法允许你做的事情是:

总是返回相同的实例(抽象单例); 只需在每次调用时创建一个新实例即可; 以规范形式返回对象(稍后会详细介绍);或 随你喜欢。

基本上,工厂方法抽象了对象创建,我个人认为强制所有构造函数为私有以强制使用此模式将是一个有趣的语言特性,但我离题了。

您可以使用此工厂方法执行的操作是缓存您创建的实例,以便对于任何两个实例 s1 和 s2,它们都遵循以下测试:

(s1 == s2) == s1.equals(s2)

所以当我说 String 不是严格规范时,它的意思是:

String s1 = "blah";
String s2 = "blah";
System.out.println(s1 == s2); // true

但正如其他人指出的那样,您可以使用以下方法更改此设置:

String s3 = new String("blah");

并且可能:

String s4 = String.intern("blah");

所以你不能完全依赖引用相等,所以你根本不应该依赖它。

作为对上述模式的一个警告,我应该指出,使用私有构造函数和工厂方法控制对象创建并不能保证引用相等意味着对象相等,因为序列化。序列化绕过了正常的对象创建机制。 Josh Bloch 在 Effective Java 中介绍了这个主题(最初是在第一版中,当时他谈到了类型安全枚举模式,后来成为 Java 5 中的一种语言特性),您可以通过重载(私有)readResolve() 方法来绕过它。但这很棘手。类加载器也会影响问题。

无论如何,这是规范的形式。

【讨论】:

+1 以获得很好的解释。但是您可能想解释一下“规范”在这种情况下的含义——JVM 拥有一个已创建字符串的表,因此它不需要重复创建相同的字符串。 Java 与 C 和 C++ 相比具有明显性能优势的少数几个地方之一。 对于 C/C++,GCC 至少有一个编译时选项来重用字符串常量。它也很聪明,可以在可能的情况下支持子字符串。但它不会在运行时执行此操作(除非您有一个执行此操作的库,例如使用 Qt 之类的隐式共享)。 +1 for "".equals(str) ...不敢相信我从来没有想到过。 拜托,我想看看你的“明显的性能优势”。 raid6.com.au/~onlyjob/posts/arena 只是说:如果s1NULL,则针对"".equals(s1) 进行测试也会返回TRUE。如果你想使用s1 作为字符串对象,你必须单独测试。【参考方案4】:
"".equals(s)

似乎是最好的选择,但Apache commons lang库中也包含Stringutils.isEmpty(s)

【讨论】:

有趣,一个库调用,它比它替换的代码更长更晦涩。 ;) 虽然我不会为此添加 commons-lang,但如果我还没有将它用于其他用途,但我有可能使用它。语句的空指针避免版本总是让我感到很头疼,我也讨厌检查空值的方式,所以我更喜欢 StringUtils 版本。 虽然它更长,但使用像 StringUtil.isNullOrEmpty(someString); 这样的库调用并不会更晦涩难懂。 ,原因是在那里有一个名字使它更具可读性。对性能的影响可以忽略不计,所以它是一场胜利。 我想这属于可读性的主观性:) 对我来说 StringUtils.isEmpty(foo) 比 "".equals(foo) 更具可读性,但我能理解 Peter Lawrey 的观点。 @PeterLawrey "" 是硬编码。即使您不输入任何内容,引号也是编码包装器。我们讨厌硬编码的事实迫使我们使用 StringUtils。【参考方案5】:

这与您最初的问题有点偏离,但总有

if(s1.length() == 0)

我相信这相当于 1.6 中的 isEmpty() 方法。

【讨论】:

如果 String 为空,这将遭受 NullPointerException。您始终可以使用 if(s1 != null && s1.length() == 0)... 这样,如果 s1 为空,您的条件将短路评估长度。 是的,但 s1.isEmpty() 或 s1.equals("") 也是如此。【参考方案6】:

给定两个字符串:

String s1 = "abc";
String s2 = "abc";

-或-

String s1 = new String("abc");
String s2 = new String("abc");

对两个 Object 执行的 == 运算符检查对象身份(如果两个运算符返回同一个对象实例,则返回 true。)应用于 java.lang.Strings 的 == 的实际行为并不总是一致,因为 String interning。

在 Java 中,字符串是 interned(至少部分由 JVM 决定。)在任何时间点,s1 和 s2 可能会或可能不会被视为相同的对象引用(假设它们具有相同的值。)因此,s1 == s2 可能返回 true,也可能不返回 true,这仅取决于 s1 和 s2 是否都已被实习。

使 s1 和 s2 等于空字符串对此没有影响 - 它们仍然可能已被拘留,也可能未被拘留。

简而言之,如果 s1 和 s2 具有相同的内容, == 可能会也可能不会返回 true。如果 s1 和 s2 具有相同的内容,则 s1.equals(s2) 保证返回 true。

【讨论】:

【参考方案7】:

如果需要空检查,请使用 String.isEmpty() 或 StringUtils.isEmpty(String str)。

【讨论】:

我希望 java 有一个 String.Empty,你可以在 C# 中设置一个字符串。这将使 isEmpty() 方法更有意义,并使变量等于空字符串更容易。【参考方案8】:

简答

s1 == ""         // No!
s1.equals("")    // Ok
s1.isEmpty()     // Ok: fast (from Java 1.6) 
"".equals(s1)    // Ok: null safe

我会确保 s1 不为 null 并使用 isEmpty()。

注意:空字符串“”不是特殊的字符串,而是算作任何其他“值”。

稍长一点的答案

对 String 对象的引用取决于它们的创建方式:

使用运算符 new 创建的字符串对象总是引用单独的对象,即使它们存储相同的字符序列,所以:

String s1 = new String("");
String s2 = new String("");
s1 == s2 // false

使用运算符 = 创建的字符串对象后跟一个用双引号括起来的值 (= "value") 存储在字符串对象池中:在池中创建新对象之前,在池中搜索具有相同值的对象,如果找到则引用。

String s1 = ""; // "" added to the pool
String s2 = ""; // found "" in the pool, s2 will reference the same object of s1
s1 == s2        // true

对于用双引号 ("value") 括起来的值创建的字符串也是如此,所以:

String s1 = "";  
s1 == "";        //true

String equals 方法对两者都进行检查,这就是编写安全的原因:

s1.equals("");

如果 s1 == null,这个表达式可能会抛出 NullPointerException,所以,如果你之前不检查 null,写起来更安全:

"".equals(s1);

另请阅读How do I compare strings in Java?

希望它可以帮助没有经验的用户,他们可能会发现其他答案有点过于复杂。 :)

【讨论】:

将字符串数组与变量Java进行比较[重复]

】将字符串数组与变量Java进行比较[重复]【英文标题】:ComparingstringarraytovariableJava[duplicate]【发布时间】:2018-08-2307:12:56【问题描述】:我有一个两难境地,我正在尝试找出将名为(code)的字符串变量与字符串数组进行比较的最佳... 查看详情

java示例代码_将对象属性名称与字符串进行比较

java示例代码_将对象属性名称与字符串进行比较 查看详情

java示例代码_将一个字符与字符串中的单个字符进行比较

java示例代码_将一个字符与字符串中的单个字符进行比较 查看详情

在保存到核心数据之前将字符串与 NSPredicate 进行比较

】在保存到核心数据之前将字符串与NSPredicate进行比较【英文标题】:ComparingstringswithNSPredicatebeforesavingtoCoreData【发布时间】:2021-06-2804:04:27【问题描述】:我正在尝试在保存到CoreData之前执行字符串比较。保存到CoreData的字符串... 查看详情

java示例代码_将数组列表的成员与字符串进行比较

java示例代码_将数组列表的成员与字符串进行比较 查看详情

java中如何将int与string作比较

...//定义一个整型int str = "232";//定义一个字符串2、把int转成stringString stra = a+"";//通过与字符串连接,转换成字符串stra3、通过equals进行比较boolean b = stra.equals(str);//比较是否一致,如... 查看详情

java示例代码_将arraylist与list进行比较<;字符串[]>;JAVA

java示例代码_将arraylist与list进行比较<;字符串[]>;JAVA 查看详情

将 java epoch 字符串与 php epoch 日期进行比较

】将javaepoch字符串与phpepoch日期进行比较【英文标题】:comparejavaepochstringwithphpepochdate【发布时间】:2017-01-1108:00:52【问题描述】:这是我有一个java字符串纪元日期,我想比较并将数据添加到SQL它给出一个解析错误不知道为什么... 查看详情

Java将字符串与正则表达式进行比较-while循环

】Java将字符串与正则表达式进行比较-while循环【英文标题】:Javacomparingstringtoregex-whileloop【发布时间】:2013-12-1618:58:05【问题描述】:我希望用户输入一个字符串,如果该字符串与我的正则表达式不匹配,那么我希望输出一条... 查看详情

java将字符串与英语以外的语言进行比较

...和英语的应用程序。我有一个列表,我希望用户输入一个字符串,以便我可以找到他的字符串是否存在于列表中。我用这个:Stringuserstring=blablabla;for(inti=0;i<allFoods.size();i++){if(allFoods.get(i).toLowerCase().contains(userstring.toLowerCase())) 查看详情

java示例代码_将一个字符串与另一个字符串中越来越小的部分进行比较

java示例代码_将一个字符串与另一个字符串中越来越小的部分进行比较 查看详情

.NET与Java的子串运算性能比较

...ETandJava【发布时间】:2011-03-2907:45:56【问题描述】:获取字符串的子字符串是一种非常常见的字符串操作操作,但我听说Java和.NET平台之间的性能/实现可能存在相当大的差异。具体来说,我听说在Java中,java.lang.String为substring提... 查看详情

将 Python 子字符串与 char 值进行比较

】将Python子字符串与char值进行比较【英文标题】:CompareaPythonsubstringtoacharvalue【发布时间】:2021-11-2003:21:43【问题描述】:我正在尝试遍历Python中的一个循环,并将字符串上的当前字符与常量字符进行比较。foriins:if(s[i]==\'I\')mySu... 查看详情

Java - 将 ArrayList 中的字符串与 .txt 文件中的所有文本进行比较

】Java-将ArrayList中的字符串与.txt文件中的所有文本进行比较【英文标题】:Java-comparingstringinArrayListtoalltextin.txtfile【发布时间】:2011-09-1519:52:36【问题描述】:实际的问题会在后面解决:),谢谢。我对Java还很陌生(几乎是通过一... 查看详情

如何将双引号字符串与字符进行比较?

】如何将双引号字符串与字符进行比较?【英文标题】:HowdoIcompareadoublequotesstringtoacharacter?【发布时间】:2020-08-0605:04:35【问题描述】:我曾尝试在C++中将字符串下标与带有空格("")的字符串进行比较,但它返回了指针比较错误... 查看详情

字符串匹配算法的使用(未完待整理)

参考技术A字符串的匹配在Java中都知道使用indexOf函数来实现,那么其匹配算法是怎么样的呢?单模式和多模式的区别就是一次遍历主串能否将多个模式的字符串都查找出来。英文全称为BruteForce,暴力匹配算法,匹配字符串的方... 查看详情

将字符串与字符序列进行比较

】将字符串与字符序列进行比较【英文标题】:Comparingastringtoasequenceofchars【发布时间】:2021-08-2713:38:24【问题描述】:我有以下字符串"long"我有一个chars数组,其中包含序列[...,[l],[o],[n],[g],...]。有人可以帮我找到一种方法来将st... 查看详情

将字符串与 CoreData 进行比较

】将字符串与CoreData进行比较【英文标题】:ComparestringwithCoreData【发布时间】:2015-04-2619:01:44【问题描述】:我有一个字符串(例如“Test”),还有一些存储在CoreData中的字符串。现在我想检查CoreData中是否也存在字符串“Test”... 查看详情