/*当使用for-each循环时,对每个取出的元素进行操作并不会影响原数据: * Integer[] a = {1,2,3}; for(Integer aa: a){ aa = 0; } System.out.println(Arrays.toString(a));//输出[1,2,3] */
起因是想练习一下重写hashCode(), 然后和编译器自动重写的hashCode返回值做对比
原预计本该输出相同值,却未达到预期
public class Late_Test {
public static void main(String[] args) {
MyDate date = new MyDate(1, 2);
System.out.println(date.hashCode());
System.out.println(date.hashCode1());
}
}
class MyDate {
private int year;
private int month;
String name;
public MyDate(int year, int month) {
this.year = year;
this.month = month;
}
public int hashCode1() {
int result = 1;
Integer i = Integer.valueOf(year);
Integer ii = Integer.valueOf(month);
result += 31 * result + (i == null ? 0 : i.hashCode());
result += 31 * result + (ii == null ? 0 : i.hashCode());
return result;
}
@Override
public int hashCode() {
return Objects.hash(year, month);
}
}
分析
给出的year和month值都在cache数组范围里,所以hashCode1()得到的对象 i 应该和 hashCode()里传给hash()的参数是同一个对象(存在自动装箱),同样的 ii 也是一样
经过debug发现的确如此
但是问题出在hash()里
public static int hash(Object... values) { return Arrays.hashCode(values); }
public static int hashCode(Object a[]) { if (a == null) return 0; int result = 1; for (Object element : a)//出问题的地方 result = 31 * result + (element == null ? 0 : element.hashCode()); return result; }
如上所言,for-each遍历a[],并不是单纯使用指针指向a[]中的元素,似乎是重新new了对象,导致element.hashCode()返回了不一样的值,得出了不同于hashCode1()的result值
另外,虽然以前就已经注意到过,但还是在这里进行强调
像Integer和int这样具有自动装箱拆箱特性的类型,在作为函数参数的时候也会体现,即上述程序调用hash()的表现
但是要注意一种特殊情况,int和Integer不是在任何情况下都可以做到兼容的
Integer[] a = {1,2}; int[] aa = {new Integer(3)}; a = aa;//error a[0] = aa[00];//right ,自动拆箱