“new Object()”似乎并没有创建一个新对象,为什么?

5

我正在经历一些奇怪的时刻。

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文档中的 Integer.toHexString(hashCode())),为什么会这样?为什么它不能每次都产生不同的字符串?或者它是因为可以重复使用同一个对象而这样做的吗?
编辑:我尝试了多次执行Java应用程序。

2
你的意思是什么?你是在循环中运行这个程序还是多次执行Java应用程序? - JB Nizet
我尝试多次执行Java应用程序。 - Peter_James
2
JVM总是从头开始,总是经历相同的步骤,直到创建对象,因此你每次看到的都是相同的。 - JB Nizet
5个回答

5

对象的哈希码通常是从其内部地址计算出来的(参见http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29),因此如果您使用相同状态重新运行程序,则内存中对象的地址很可能每次都相同。

严格来说,这并不是重用同一对象,因为您正在退出JVM;每次只是按照相同的步骤,在相同的内存位置创建一个完全相同的对象,这会产生一个相同的哈希码,以便toString()方法返回。


1
新对象刚好在之前的内存位置上创建,经过几次执行后,它预计会发生变化。您可以尝试执行该程序10次,我感觉至少有2-3次对象将在不同的位置创建。
这种JVM行为不能被认为是错误的。在Java中查看内存位置甚至是错误的,JVM在执行过程中有选项将对象移动到不同的内存位置。

-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]


-1

来自Object.hashCode文档:

hashCode的一般契约是:

  • 在Java应用程序执行期间,每当同一对象被多次调用时,只要在equals比较中使用的信息未被修改,hashCode方法必须始终返回相同的整数。这个整数不需要在应用程序的一个执行与另一个执行之间保持一致。
  • 如果两个对象根据equals(Object)方法是相等的,则在这两个对象上调用hashCode方法必须产生相同的整数结果。
  • 如果两个对象根据equals(java.lang.Object)方法是不相等的,则不要求在这两个对象上调用hashCode方法会产生不同的整数结果。然而,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

因此,您的对象始终具有相同的hashCode是有效的。


-1

是的,就像你说的那样。我尝试执行Java应用程序多次,结果与你所说的一样。但是,这些结果只在我们执行Java应用程序时才会出现。然而,在Eclipse中重新编译Java应用程序时,结果并不相同。就像这样,您将获得不同的哈希码值。首先,JVM在第一次执行Java程序时将字节文件加载到内存中。每次执行都会获得相同的哈希码值,就像“Rich Smith”回复的那样。每次编译程序时都会将字节文件加载到内存中。因此,我们将获得不同的哈希码值并获得不同的对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接