简体   繁体   English

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

[英]Serializable classes and the == operator

Here is the source code of the String.equals method:下面是 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;
}

Since String is Serializable, does it make sense to use the == operator in the String.equals method?由于 String 是可序列化的,那么在 String.equals 方法中使用 == 运算符是否有意义? If we try to compare two different String objects, maybe with the same memory address, located on different VM, will this work correctly?如果我们尝试比较两个不同的 String 对象,可能具有相同的 memory 地址,位于不同的 VM 上,这会正常工作吗?

In my own code I use equals method to compare two strings.在我自己的代码中,我使用 equals 方法来比较两个字符串。 I know what == does.我知道 == 做什么。 I am asking if it make sense to have a == comparison in the equals method of the String class.我在问在字符串 class 的 equals 方法中进行 == 比较是否有意义。

It makes perfect sense to use the == because if both the instance of string point to same reference they have to be equal so no need to compare the characters使用 == 非常有意义,因为如果字符串的两个实例都指向相同的引用,它们必须相等,因此无需比较字符

Yes it makes sense, because java uses a pool of Strings, so when you create a String without using the new keyword, as long as both reference variables are the same String == will always be true.是的,这是有道理的,因为 java 使用了一个字符串池,所以当你创建一个不使用 new 关键字的字符串时,只要两个引用变量相同,字符串 == 将始终为真。

Say you have "" in your string pool, if you do假设你的字符串池中有“”,如果你这样做了

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

Since "" is in the string pool, they will in fact be pointing to the same memory location and therefore由于 "" 在字符串池中,它们实际上将指向相同的 memory 位置,因此

a == b 

Would be true会是真的

In fact as long as you don't use其实只要你不使用

 String c = new String("");

The reference variable will always be pointing to the "" in the String pool.引用变量将始终指向字符串池中的“”。

However when you use the new keyword a new memory allocation is created outside of the String pool.但是,当您使用 new 关键字时,会在字符串池之外创建一个新的 memory 分配。 Therefore if you do:因此,如果您这样做:

 c == b

This will return false, because the reference to b is in the String pool, but the reference for c is not, it is outside the pool这将返回 false,因为对 b 的引用在字符串池中,但对 c 的引用不在,它在池外

However if we did但是,如果我们这样做了

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

This will return true, what intern does per the comments on the String class is这将返回 true,实习生根据对字符串 class 的评论所做的事情是

Returns a canonical representation for the string object.返回字符串 object 的规范表示。 A pool of strings, initially empty, is maintained privately by the class String.最初为空的字符串池由 class 字符串私下维护。

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned.当调用 intern 方法时,如果池中已经包含一个等于该 String object 的字符串,由 equals(Object) 方法确定,则返回池中的字符串。 Otherwise, this String object is added to the pool and a reference to this String object is returned.否则,此字符串 object 将添加到池中,并返回对此字符串 object 的引用。

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.由此可见,对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为真时,s.intern() == t.intern() 才为真。

As some already pointed out when the object is deserialized on the other JVM, it will be using that JVM String pool正如一些人已经指出的那样,当 object 在另一个 JVM 上反序列化时,它将使用 JVM 字符串池

Serializable means that an instance of the class can be converted into bytes and back into a an object instance using Java's default serialization mechanisms.序列化意味着可以使用 Java 的默认序列化机制将 class 的实例转换为字节并返回为 object 实例。 When an object is deserialized, a new object instance is created based on the bytes and that instance exists in the JVM where it was deserialized.当反序列化 object 时,会根据字节创建一个新的 object 实例,并且该实例存在于反序列化的 JVM 中。 Serialization/deserialization does not magically make the same object instance accessible in multiple JVMs, but it just creates new object instances which are copies of each other.序列化/反序列化不会神奇地使同一个 object 实例在多个 JVM 中可访问,但它只是创建新的 object 实例,它们是彼此的副本。

Two JVMs cannot share object instances, so it's not possible that the == operator could be used to compare the addresses of object instances from different address spaces.两个 JVM 不能共享 object 实例,因此不可能使用 == 运算符来比较来自不同地址空间的 object 实例的地址。

This IF case in the java api is an optimization. java api 中的这种 IF 案例是一种优化。 Because the Virtual Machine holds a String Cache and optimizes some (not all) Strings to literals.因为虚拟机拥有一个字符串缓存并将一些(不是全部)字符串优化为文字。 Some literals hold the same object reference.一些文字具有相同的 object 引用。

With my JDK eg使用我的 JDK,例如

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

equals to true.等于真。 Because both are in the Literal cache of my jvm.因为两者都在我的 jvm 的 Literal 缓存中。 But its not enough to compare the object reference because not every String is saved in the literal cache.但它不足以比较 object 参考,因为并非每个字符串都保存在文字缓存中。

eg例如

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

will always be false because you explicitly call for a new object reference.将始终为 false,因为您明确调用了新的 object 参考。

But even in the above case但即使在上述情况下

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

will also equal to true.也将等于 true。

There is also another post on this: Using static variables for Strings还有另一篇文章: Using static variables for Strings

Assuming that you are speaking about the following code snippet:假设您正在谈论以下代码片段:

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

It makes sense to use the == operator, since it will be only true when both strings are pointing to the same memory address.使用 == 操作符是有意义的,因为只有当两个字符串都指向同一个 memory 地址时它才是正确的。 This is probably done in java.lang.String to optimize string comparison when string literals are used.这可能在 java.lang.String 中完成,以在使用字符串文字时优化字符串比较。 You can check http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html for detailed description of how string literals are pooled in Java.您可以查看http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html详细描述如何在 ZD523817880E1EA2138 中汇集字符串文字

If we try to compare two different String objects, maybe with the same memory address, located on different VM, will this work correctly?如果我们尝试比较两个不同的 String 对象,可能具有相同的 memory 地址,位于不同的 VM 上,这会正常工作吗?

You can't do that.你不能那样做。 There is no way of comparing Strings in two VMs, with or without the == operator.无论有没有 == 运算符,都无法比较两个 VM 中的字符串。 Your question therefore isn't about anything.因此,您的问题任何事情无关。 You would have to get them both into the same VM, whereupon you would call String.equals().您必须将它们都放入同一个 VM,然后调用 String.equals()。

The == test is just a shorthand to avoid going through all the rest of the code. == 测试只是避免遍历代码的所有 rest 的简写。 It is has nothing to do with Serialization whatsoever.它与序列化无关。 And different VMs cannot possibly come into it.并且不同的虚拟机不可能进入它。

No. Since "String" is not a primative type using == simply compares the address of the object and not the contents itself.不,因为“字符串”不是原始类型,所以使用 == 只是比较 object 的地址而不是内容本身。 By executing:通过执行:

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

if (a == b)

You would get false because although string a & string b are the same their representations in memory are different.您会得到错误,因为尽管字符串 a 和字符串 b 相同,但它们在 memory 中的表示不同。

The.equals() method is used to compare Strings (also, Objects) within Java as it compares the contents of the Object. .equals() 方法用于比较 Java 中的字符串(也称为对象),因为它比较了 Object 的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM