可序列化的类和==运算符

时间:2011-06-28 19:27:10

标签: java serialization equals

以下是String.equals方法的源代码:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
}

由于String是Serializable,在String.equals方法中使用==运算符是否有意义?如果我们尝试比较两个不同的String对象,可能是位于不同VM上的相同内存地址,这是否可以正常工作?

在我自己的代码中,我使用equals方法来比较两个字符串。我知道==做什么。我问的是在String类的equals方法中进行==比较是否有意义。

7 个答案:

答案 0 :(得分:3)

使用==非常有意义,因为如果字符串的实例都指向相同的引用,则它们必须相等,因此不需要比较字符

答案 1 :(得分:1)

是的,这是有道理的,因为java使用了一个字符串池,因此当你创建一个不使用new关键字的String时,只要两个引用变量都相同,String ==将始终为true。

假设你的字符串池中有“”,如果你这样做

String a = "";
String b = "";

由于“”在字符串池中,它们实际上将指向相同的内存位置,因此

a == b 

是真的

实际上只要你不使用

 String c = new String("");

引用变量将始终指向String池中的“”。

但是,当您使用new关键字时,会在String池之外创建新的内存分配。因此,如果你这样做:

 c == b

这将返回false,因为对b的引用在String池中,但c的引用不在,它在池外

但是,如果我们这样做了

 String d = c.intern()
 d == b

这将返回true,对于String类的注释是什么实习生

返回字符串对象的规范表示。 最初为空的字符串池由String类私有维护。

当调用intern方法时,如果池已经包含一个等于此String对象的字符串(由equals(Object)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回对此String对象的引用。

接下来,对于任何两个字符串s和t,当且仅当s.equals(t)为真时,s.intern()== t.intern()才为真。

正如一些人已经指出的那样,当对象在另一个JVM上反序列化时,它将使用该JVM字符串池

答案 2 :(得分:1)

Serializable表示可以使用Java的默认序列化机制将类的实例转换为字节并返回到对象实例中。反序列化对象时,将根据字节创建新的对象实例,并且该实例存在于JVM中,并在其中进行反序列化。序列化/反序列化不会神奇地使多个JVM中可以访问相同的对象实例,但它只是创建了彼此副本的新对象实例。

两个JVM无法共享对象实例,因此不可能使用==运算符来比较来自不同地址空间的对象实例的地址。

答案 3 :(得分:1)

java api中的这种IF情况是一种优化。因为虚拟机拥有一个字符串缓存并将一些(不是全部)字符串优化为文字。一些文字持有相同的对象引用。

使用我的JDK,例如

String a = "ABCD";
String b = "ABCD";
if (a==b)

等于true。因为两者都在我的jvm的Literal缓存中。但它还不足以比较对象引用,因为不是每个String都保存在文字缓存中。

e.g。

String a = new String("ABCD");
String b = new String("ABCD");
if (a==b)

将始终为false,因为您显式调用了新的对象引用。

但即使在上述情况下

if(a.intern()==b.intern())

也等于真。

还有另一篇文章:Using static variables for Strings

答案 4 :(得分:0)

假设您正在谈论以下代码段:

if (this == anObject) {
    return true;
}

使用==运算符是有意义的,因为只有当两个字符串都指向同一个内存地址时才会出现这种情况。这可能在java.lang.String中完成,以在使用字符串文字时优化字符串比较。您可以查看http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html以获取有关如何在Java中池化字符串文字的详细说明。

答案 5 :(得分:0)

  

如果我们尝试比较两种不同的   字符串对象,可能与之相同   内存地址,位于不同的地方   VM,这会正常工作吗?

你做不到。无论使用或不使用==运算符,都无法在两个VM中比较字符串。因此,您的问题不是关于任何事情。您必须将它们都放入同一个VM中,然后调用String.equals()。

== test只是一种速记,可以避免遍历所有其余的代码。它与序列化无关。不同的虚拟机不可能进入它。

答案 6 :(得分:-4)

没有。由于“String”不是主要类型,使用==只是比较对象的地址而不是内容本身。执行:

String a = "ABCD";
String b = "ABCD";

if (a == b)

你会得到假的,因为虽然字符串a&字符串b与它们在内存中的表示形式是不同的。

.equals()方法用于比较Java中的字符串(也称为Objects),因为它比较了Object的内容。