覆盖 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字符串常量表达式,更准确
你可能知道对象有一些功能, 例如,我们有来自 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 hadString s = new String("a"); String s2 = new String("a");
I used 2 space in memory, but when i useString s = "a"; String s2 = "a"
I use 1 space in memory. So that's meantoString()
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字符串常量表达式,更准确