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

Java 可序列化类和==运算符,java,serialization,equals,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 == ano

以下是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是可序列化的,那么在String.equals方法中使用==运算符有意义吗?如果我们尝试比较两个不同的字符串对象,可能具有相同的内存地址,位于不同的VM上,这会正常工作吗


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

否。因为“String”不是一种主要类型,使用==只是比较对象的地址,而不是内容本身。通过执行:

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

if (a == b)
您将得到false,因为尽管字符串a和字符串b相同,但它们在内存中的表示形式不同


.equals()方法用于比较Java中的字符串(也包括对象),因为它比较对象的内容。

是的,这很有意义,因为Java使用一个字符串池,所以当您在不使用new关键字的情况下创建字符串时,只要两个引用变量相同,String==将始终为真

假设字符串池中有“”,如果有

String a = "";
String b = "";
由于“”位于字符串池中,它们实际上将指向同一内存位置,因此

a == b 
那是真的

事实上只要你不使用

 String c = new String("");
引用变量将始终指向字符串池中的“”

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

 c == b
这将返回false,因为对b的引用在字符串池中,而对c的引用不在字符串池中,它在字符串池之外

但是如果我们这样做了

 String d = c.intern()
 d == b
这将返回true,intern根据String类上的注释所做的是

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

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

因此,对于任意两个字符串s和t,s.intern()==t.intern()为真当且仅当s.equals(t)为真时

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

意味着可以使用Java的默认序列化机制将类的实例转换为字节并返回到对象实例。当一个对象被反序列化时,将基于字节创建一个新的对象实例,并且该实例存在于反序列化它的JVM中。序列化/反序列化不会神奇地使同一个对象实例在多个JVM中可访问,但它只会创建彼此副本的新对象实例


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

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

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

用我的JDK

String a = "ABCD";
String b = "ABCD";
if (a==b)
等于真。因为它们都在jvm的文本缓存中。但是比较对象引用是不够的,因为不是每个字符串都保存在文本缓存中

e、 g

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

但即使在上述情况下

if(a.intern()==b.intern())
也将等于真


这里还有另一篇文章:

假设您谈论的是以下代码片段:

if (this == anObject) {
    return true;
}
使用==运算符是有意义的,因为只有当两个字符串都指向同一内存地址时,它才是真的。这可能是在java.lang.String中完成的,以便在使用字符串文本时优化字符串比较。您可以查看Java中如何汇集字符串文字的详细描述

如果我们试着比较两个不同的 字符串对象,可能具有相同的 内存地址,位于不同的 VM,这能正常工作吗

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


==测试只是一个简写,以避免遍历代码的其余部分。它与序列化无关。在这个示例代码中,您很可能会得到一个true,因为javac将对它进行优化,使两个变量指向相同的文本。我使用equals方法比较两个字符串。我知道==做什么。我想问的是,在字符串的equals方法中进行==比较是否有意义。之所以有意义,是因为在equals方法中,它比较的是原语字符。下面的一些答案针对的是另一个问题。根据您下面的评论,你误解的是Serializable的真正含义。我根据OP的评论编辑了这个问题。这是你真正想问的吗?字符串是可序列化的。如果我们尝试比较两个不同的字符串对象,可能是位于不同VM上的具有相同内存地址的对象,这会正常工作吗?如果我能够在JVM中使用字符串,那么字符串就在这个JVM中。如果它在另一个JVM中,我将无法使用它。可序列化仅意味着可以将对象转换为字节流以发送到其他地方。但是,当它被反序列化时,它将成为JVM中具有反序列化的另一个字符串实例
if (this == anObject) {
    return true;
}