3

首先,我在这里谈论的是默认的 hashCode() 方法,而不是被覆盖的东西。当我们创建一个新对象时,'new' 操作符返回它创建的那个对象的内存地址;在java中我们说它更普遍地返回引用。我想知道的是,这和hashCode()返回的值一样吗?

我相信它们是一样的。但是话又说回来,当我们有超过 2^32 个对象并且给定 hashCode() 返回一个整数(2^32 个不同的数字)时,到处都会发生冲突,当我们传递对象时,这将是一个真正的混乱。JVM是如何处理的?

4

5 回答 5

5

当我们创建一个新对象时,'new' 操作符返回它创建的那个对象的内存地址;在java中我们说它更普遍地返回引用。

好吧,引用当然不必是地址。这是一种引用对象的方式 - 位的确切值取决于 JVM 实现。

我想知道的是,这和hashCode()返回的值一样吗?

不必要。你当然不应该在这方面做出任何假设。同样,这是一个实现细节。

值得记住的是,虽然垃圾收集器可以在内存中移动对象(随时更新引用),但哈希码不能基于此更改,这是反对您建议的论据。

但是话又说回来,当我们有超过 2^32 个对象并且给定 hashCode() 返回一个整数(2^32 个不同的数字)时,到处都会发生冲突,当我们传递对象时,这将是一个真正的混乱。

会有哈希码冲突,是的。这是不可避免的——任何使用哈希码的东西都需要考虑到冲突的可能性。但是不能存在引用冲突——能够同时支持超过 2 32 个值的 JVM 显然不能使哈希码和引用具有相同的值。

于 2012-06-16T08:07:23.550 回答
2

在java中我们说它更普遍地返回引用。我想知道的是,这和hashCode()返回的值一样吗?

Object#HashCode(我的亮点):

在合理可行的情况下,由 Object 类定义的 hashCode 方法确实为不同的对象返回不同的整数。(这通常通过将对象的内部地址转换为整数来实现,但 JavaTM 编程语言不需要这种实现技术。)

所以这对程序员来说是不透明的。
您需要知道的是,通过new您获得handler对象的 a 并且 ahashCode是基于将内部地址转换为表示对象 hashCode 的整数的“配方”,无论您的内存区域如何,这都是相同的对象当前位于(例如由于 GC 移动)

于 2012-06-16T08:19:33.073 回答
1

由于哈希码不需要唯一,所以如果在 64 位空间中转换两个对象的地址导致哈希码冲突是没有问题的:不要求不同对象的哈希码不同 - 只需要相等对象的哈希码相同。

在 Real Life TM中,默认hashCode值看起来确实与对象的地址非常相似。然而,这些信息对 Java 程序员没有用处:即使哈希码等于对象的地址,Java 也没有提供一种机制来利用这些知识,使其成为无用的实现细节。

于 2012-06-16T08:09:44.060 回答
0

new在 Java 中不返回内存地址。甚至更多:Java 可以(并且确实)在内存中重新定位对象。因此,尽管hashCode()Java 中的实现可以返回一个内存地址,但它可能不会,因为它在对象的整个生命周期内都不稳定。

hashCode 不必是唯一的。在 hashCode 用于识别对象的情况下(例如 in HashMap),它需要与 的实现配对equals()以解决冲突。

于 2012-06-16T08:09:05.240 回答
0

当我们创建一个新对象时,'new' 操作符返回它创建的那个对象的内存地址

不,它返回一个 Java 引用。由于垃圾收集和对象可以移动的含义,您可以打赌的一件事是它不是内存地址。

这与 hashCode() 返回的值相同吗?

不,hashCode 不是内存地址,尤其是在 hashCode() 已被覆盖的情况下。

我相信它们是一样的。

你的信念是没有根据的。

但是话又说回来,当我们有超过 2^32 个对象并且给定 hashCode() 返回一个整数(2^32 个不同的数字)时,到处都会发生冲突,当我们传递对象时,这将是一个真正的混乱。JVM是如何处理的?

所以很明显你的信念是错误的。还要考虑 64 位实现。这里唯一的问题是你的假设。

于 2012-06-16T12:31:46.350 回答