我们Java中常说的判断相等有两种:== 和 equals方法。
应用范围:
我们常将 == 用于基本类型的判断,equals常用于引用类型的判断。
判断原理:
== :Java中会先判断他们的哈希值,哈希值相同时,再对其地址进行判断,地址相同返回true。其实这里很多人会说先去判断相不相等,其实在哈希值就是根据不同的规则生成的,一般情况都与值是密切相关的。
equals : 在引用类型判断时,我们使用它,两值判断哈希值相同就返回true,不用比较地址。
二、哈希值 == 地址?废话不多说,直接上题目:
String s = "1";
String s2 = "1";
String s3 = "12";
String s4 = s + "2";
System.out.println(s == s2);
System.out.println(s3 == s4);
System.out.println(s.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
1、 判断 s == s2 结果为true|false?
2、判断 s3 == s4 结果为true|false?
3、判断 s.hashCode() == s2.hashCode() 结果为true|false?
4、判断 s3.hashCode() == s4.hashCode() 结果为true|false?
好了,上结果:
String s = "1"; String s2 = "1"; String s3 = "12"; String s4 = s + "2"; System.out.println(s == s2);//true System.out.println(s3 == s4);//false System.out.println(s.hashCode() == s2.hashCode());//true System.out.println(s3.hashCode() == s4.hashCode());//true System.out.println(s.hashCode());//49 System.out.println(s2.hashCode());//49 System.out.println(s3.hashCode());//1569 System.out.println(s4.hashCode());//1569
可以看到,
第一个结果s和s2的哈希值一样,他们返回true,说明他们地址也是一样的。也就是说在常量的赋值过程中,Java会自动默认在你存储新的变量时根据hash值分配统一地址,这样就可以大大避免内存的浪费。
第二个结果s3和s4的哈希值也是一样的,但返回的却是false,再次验证 == 是判断地址是否相同的,同样我们也可以得到一个结论:哈希值和地址并不是一个东西,他们有自己各自的分配和实现体系。
三、哈希值生成原理其实在Java的类中,并没有完全规定死所有的哈希值生成规则。所以我们在创建Javabean的时候,总能看到这个方法。
所以我们常见的Javabean中其实我们可以自己去设置简易的规则,这两个方法主要是根据你的选择来生成不同的判断相等的形式。
如果你没有重写这两个方法,系统有默认的方法。
例:
class Person{ private int id; private String name; public Person(int id, String name) { this.id = id; this.name = name; } }
对上面的Person类没有重写方法,结果
可以看到,即便构造函数参数一样,每次new 对象的时候都会生成一个不同的哈希值。
当我们重写方法时只用名字来作为区别:
class Person{ private int id; private String name; public Person(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name); } }
由此,也算是我们以自己的方式来选择生成不同情况的hash值。所以我们常用类像包装类,在他们的原码中也都有相应的重写了的规则,大家有想法的可以去看看。
这里将的是我们自己类生成规则,我们再来看一个我们最常用的String类的哈希值生成规则吧:
其实,String的生成规则很简单,相信眼尖的大家在最开始的时候就已经看出来了:
String s = "1"; String s2 = "1"; String s3 = "12"; String s4 = s + "2"; System.out.println(s.hashCode());//49 System.out.println(s2.hashCode());//49 System.out.println(s3.hashCode());//1569 System.out.println(s4.hashCode());//1569
如果对ASSIC码熟悉的已经看出来了,1的ASSIC码正是49.。所以首先我们就知道字符串的哈希值是与字符的ASSIC码有关系的。具体是什么关系呢?
“1” 的 hashCode 是 49
“12” 的 hashCode 是 1569
“12”刚好是“1”的49 *31 +“2” 的50 =1569,对不对呢?
我们再推测一下,a的ASSIC码是97 ,b的ASSIC码是98,
所以“ab”应该是 97*31+98 = 3007+98 = 3105,是不是呢?
没错,是这样的。
好了,总结一下,哈希值和地址并不是指同一个东西。哈希值主要是针对你要存的目标值进行,而地址就是指在内存中的唯一位置。在Java中二者相辅相成,大大提高数据的 *** 作效率。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)