将字符串与空字符串(Java) [英] Comparing a string with the empty string (Java)

查看:208
本文介绍了将字符串与空字符串(Java)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题要比较一个字符串与Java中的空字符串。如果我将一个字符串与 == 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("")) 

我知道应该用 equals 而不是 == 来比较字符串code>,但我想知道是否对空字符串很重要。

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.

推荐答案

s1 == ""

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

is not reliable as it tests reference equality not object equality (and String isn't strictly canonical).

s1.equals("")

更好,但可能遭受空指针异常。更好的是:

is better but can suffer from null pointer exceptions. Better yet is:

"".equals(s1)

没有空指针异常。

EDIT: 规范形式。本文将其定义为:

Ok, the point was asked about canonical form. This article defines it as:


假设我们有一些对象的集合S,具有等价关系的
。 A
规范形式通过将S的一些对象指定为在规范的
形式中来给出,使得在
考虑下的每个对象正好等于
一个

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.

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

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通常写成使得gcd(最大公约数)为1.所以它们将被简化为3/2。 3/2可以被视为这组有理数的规范形式

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:

public class MyInt {
  private final int number;

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

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

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:

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:


  • 总是返回相同的实例(抽象单例);

  • 每次调用都创建一个新的intsance;

  • 规范形式返回对象

  • 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.

这个工厂方法可以做的是缓存您创建的实例,对于任何两个实例s1和s2,他们遵守以下测试:

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.equals(s2)

所以当我说String不是严格的规范,这意味着:

So when I say String isn't strictly canonical it means that:

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");

且可能:

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

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

So you can't rely on reference equality completely so you shouldn't rely on it at all.

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

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.

这篇关于将字符串与空字符串(Java)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆