class Main {
public static void main(String[] args) {
int [][] a=new int[4][3];
System.out.print(a[0]);//这里从1到4地址都一样
for(int i=0;i<a.length;i++)
System.out.print(a[i]);//这里全部输出就不同,
// 为什么
}
}
你确定四个地址都一样???
class Main {
public static void main(String[] args) {
int[][] a = new int[4][3];
System.out.println(a[0]);
System.out.println(a[1]);
System.out.println(a[2]);
System.out.println(a[3]);
// for (int i = 0; i < a.length; i++) {
// System.out.print(a[i]);
//
// }
}
}
题主的问题似乎有点不太准确?
System.out.print(a[0]);//这里从1到4地址都一样
你只打了一次呀,具体指什么1到4?是指:
System.out.println(a[0]);
System.out.println(a[1]);
System.out.println(a[2]);
System.out.println(a[3]);
吗?
要回答你这个问题,首先得看System.out.println(obj);做了什么?debug,或者直接点方法名进去看,会发现最终其实只是调用了obj.toString()方法,obj.toString方法如下。
return getClass().getName() + "@" + Integer.toHexString(hashCode());
也就是说,默认不重写toString方法的时候,你所谓的“相同的地址”,其实只是一个hashcode,那么问题转换成了为什么每次换对象后重新运行hashcode会相同?
那再看hashCode的源码,发现是个native方法,也就是由c写的,以下是c计算hashcode方法所在的源码(最终调用的方法为get_next_hash)
在默认情况下计算hashcode的时候,jdk8采用的是Marsaglia's xorshift scheme算法。讲人话就是一共用了4个参数来计算,其中3个是固定的,1个是随机数,且和什么对象无关,只和你现在写的主线程(也就是main)有关。既然3个是固定的,1个是随机的,那么问题又变成了这个随机数为什么每次重新运行会相同?
通过下面的计算随机数方法所在的源码可以看出(最终调用的方法为os::random),生成随机数的时候都是固定的序列,因此,每次生成hashcode的时候总是按照一定的顺序生成。
结论:你每次重新运行,生成的hashcode就永远是同样的序列,例如1、2、3、4、5、6...,只是这里的1、2、3、4、5、6...被映射成了更复杂的序列,无论你换什么对象,因为默认情况下hashcode和对象无关。当然,重写了hashcode的对象自然不适用上文所说的内容,还有就是生成过hashcode的对象不会重复生成,会进行缓存。
另外,如果你想看真实的内存地址,请在启动项加上-XX:hashCode=4,在get_next_hash方法中可以看hashCode的生成策略。