覆盖 hashCode 后,toString() return 同一对象的相同值但在使用“==”后 return false

After override hashCode, toString() return the same value for the same object but after using "==" return false

你可能知道对象有一些功能, 例如,我们有来自 oracle Documentacion 的 toString(),我们可以知道默认情况下它是 hashCode() 的 return HexValue https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString() 我们也可以使用 hashCode() 来检查相等对象(当然实现取决于你) 所以我为我的 Class Projekt 实现了:

public class Projekt {

    int i;
    public Projekt(int i) {
        this.i=i;
        // TODO Auto-generated constructor stub
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + i;
        return result;
    }   
}

测试代码:

Projekt projekt = new Projekt(1);
System.out.println(projekt.toString());
System.out.println(projekt.toString() == projekt.toString());

输出:

Projekt@20
false

我还尝试通过以下方式在 StringPool 中获取 projekt.toString() 中的值:

    String string = projekt.toString();
    String stringABC = projekt.toString();
    System.out.println(string == stringABC);

根据 PoolString,我应该有相同的引用,但 outPrint 是错误的。

所以这个方法return不同的参考价值,但我不明白为什么?

这是因为"toString()"方法returns一个字符串。所以每次你调用 toString() 它 returns 一个新的引用因为字符串是不可变的(即使它们是相同的文本)

String class 只是指向内存中某处字符串(char)数据的指针。它是一个 class,它不是 boolean、byte、char、short、int、long、float 和 double 等原始类型。

因此,比较两个字符串就是比较指针。

您在以下位置生成了两个字符串:

String string = projekt.toString();
String stringABC = projekt.toString();

所以你现在有 2 个不同的指针。它们里面的文字是一样的,但是在内存中的位置不同

但是你可以使用对象的equals()方法:

System.out.println(string.equals(stringABC));

来自您的评论:

I copied this from diffrent comenatry: But to save memory we're using StringPool. If we have the same value, refereance is also the same it's working just for creating String not by constructor. If i had String s = new String("a"); String s2 = new String("a"); I used 2 space in memory, but when i use String s = "a"; String s2 = "a" I use 1 space in memory. So that's mean toString() return "new String()"?

你的消息来源应该说:

...it's working just for creating String using string literals.

这样可能会更清楚,因为有很多方法可以创建新的 String 对象而无需直接调用构造函数。字符串文字是那些被 " 包围的东西(包括引号),例如 "a""b""Welcome to Stack Overflow"

只有字符串文字1 会自动合并。您可以通过调用 intern().

手动将字符串放入池中

当您连接两个字符串时(例如 stringA + stringB),通常会创建一个新字符串,如 here 所述。

现在让我们看看 Object.toString 做了什么:

The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

getClass().getName() + '@' + Integer.toHexString(hashCode())

请注意,字符串在这里被连接起来,因此在这里创建了一个新的字符串对象,因此输出。

并回答以下问题:

So that's mean toString() return "new String()"?

是的,但不是直接的。编译器会将 Object.toString 中的 + 运算符转换为使用 StringBuilder 的一些代码(或者更确切地说, "the compiler has turned..." 因为 Object class 已经编)。最后,它将调用 StringBuilder.toString,这将创建一个新的 String 对象。


1字符串常量表达式,更准确