问题
在java中直接用输出语句输出一个对象,输出的结果是
类名@XXXX
,这里的XXX究竟是不是地址?
初步尝试
我们都知道,当直接输出一个对象时,会默认调用这个对象的toString
方法,那么这个toString方法到底做了什么?
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
不难发现他是调用hashcode
这个方法,那么这个方法做了什么?
public native int hashCode();
可以看到他是一个native
方法,代表其底层不是java实现的。
小试牛刀
那么我们尝试阅读下jvm源码?
试试就逝世
经过摸爬滚打,我们终于看到了其底层实现。
看到了他一共有5种策略模式
- 随机数
- 基于对象内存地址的函数
- 1
- 自增序列
- 对象地址转换为int
我们先给出研究结论:那么这个
hashcode
是地址吗?
答:是但不完全是。
初入江湖
你说的就对? 我们凭什么相信你呢?
通过阅读相关文献我们发现,jvm里面有个可选参数
XX:hashCode
,那么我们通过修改 jvm启动参数来修改策略模式,看看和我们预想的一样不一样。
为了保证结果一致性:这里我们采用策略3 恒为1 更方便观察。
编写代码
class A {
private int x;
A(int x) {
this.x = x;
}
}
public class ObjAddr {
public static void main(String[] args) {
System.out.println(new A(1));
System.out.println(new A(2));
System.out.println(new A(2).equals(new A(2)));
}
}
修改jvm参数
结果
A@1
A@1
false
想必到这里大家已经看明白了吧,无论我new多少个对象他们的"地址"都等于1
那我我们再试试别的策略?
来看看随机数策略
A@e766186
A@7dfcabd4
false
A@4d91e365
A@46f7ba12
false
每次运行值都不一样,看样子挺满足地址条件的,毕竟地址是一直变动的。
我们试试最后一个策略
A@6ac2ba68
A@6ac2bd98
false
A@6ac2ba68
A@6ac2bd98
false
A@6ac2ba68
A@6ac2bd98
false
无论运行多少次,都是同一个值 这真的是内存地址吗?
结论
严格意义上说并不是地址,但是初学者可以近似理解为地址
具体结果要看jvm的策略模式