我有一个奇怪的时刻。
ArrayList<Object> a = new ArrayList<Object>();
a.add(new Socket());
a.add(new Thread());
a.add("three");
a.add(a);
a.add(new Object());
for(Object output : a) {
System.out.println(output);
}
输出:
Socket[unconnected]
Thread[Thread-0,5,main]
three
[Socket[unconnected], Thread[Thread-0,5,main], three, (this Collection)]
java.lang.Object@615e7597
每次运行时,新对象总是提供相同的十六进制字符串(Java doc Integer.toHexString(hashCode())
),为什么会这样?为什么每次都不会产生不同的字符串?或者它是否重复使用同一个对象,因为它可以?
编辑:我多次尝试执行Java应用程序。
答案 0 :(得分:5)
对象的哈希码通常是从其内部地址(ref http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29)计算的,所以如果你重新运行具有相同状态的程序,则内存中对象的地址可能是相同的每一次。
技术上并没有重用同一个对象,因为你正在退出JVM;它只是每次都遵循相同的步骤,在内存中的相同位置创建一个相同的对象,这会产生相同的哈希码,以便toString()返回。
答案 1 :(得分:1)
新对象恰好在与之前相同的内存位置创建,几乎没有执行。预计会发生变化。您可能会尝试执行该程序10次,我觉得至少2-3次将在不同的位置创建对象。
此JVM行为不能声称为错误。甚至在java中查看内存位置也是错误的,JVM可以选择在执行过程中将对象移动到不同的内存位置。
答案 2 :(得分:-1)
来自Object.hashCode文档:
hashCode的一般合约是:
因此,您的Object始终具有相同的hashCode是有效的。
答案 3 :(得分:-1)
如果System.out.println
找到对象引用,则始终打印toString()
方法。这里List
存储不同的对象引用,具有不同的toString
实现。
ArrayList<Object> a = new ArrayList<Object>();
a.add(new Socket());
例如,Socket
类toString
被覆盖为
public String toString() {
try {
if (isConnected())
return "Socket[addr=" + getImpl().getInetAddress() +
",port=" + getImpl().getPort() +
",localport=" + getImpl().getLocalPort() + "]";
} catch (SocketException e) {
}
return "Socket[unconnected]";
}
因此,您会看到new Socket()
的输出为Socket[unconnected]
答案 4 :(得分:-1)
是的,就像你说的那样。我试图多次执行Java应用程序。结果和你说的一样。但是,结果就在我们执行Java应用程序时。但是,当我们在eclipse中重新编译 Java应用程序时,结果并不相同。像这样,你将得到不同的哈希码值。首先,JVM会在第一次执行 java程序时将字节文件加载到内存中。每次执行都会得到相同的哈希码值,就像“Rich Smith”的回复一样。编译程序时,每次都会将bytes文件加载到内存中。所以我们将得到不同的hashcode值并得到不同的Object。