Java 中"=="、equals、hashcode相关
2011-11-24 10:44
387 查看
文章属于转载,原文地址: http://zackey.iteye.com/blog/949535
1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。
通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode
4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。
以下是测试代码。
《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。
重写该方法,影响m1.equals(m2)
public boolean equals(Object o){
return true;
}
重写该方法,影响m1.hashCode()和m2.hashCode()的输出
public int hashCode(){
return 111;
}
另外,当hashCode不等的时候,向HashMap中存放值
Map map = new HashMap();
map.put(m1, m1);
map.put(m2, m2);
System.out.println(map.size());
System.out.println(map.containsKey(m1));
System.out.println(map.containsKey(m2));
会放入2个,就算equals是true
如果hashCode相等,会存放入1个
另外:设计hashcode()时最重要的因素是——无论何时,对于同一个对象调用hashcode()都应该生成同样的值。
附上一段出自Java 编程思想的代码
输出结果是:
{String: hi id: 4 hashCode(): 146450=3, String: hi id: 1 hashCode(): 146447=0, String: hi id: 3 hashCode(): 146449=2, String: hi id: 5 hashCode(): 146451=4, String: hi id: 2 hashCode(): 146448=1}
Looking up String: hi id: 1 hashCode(): 146447
0
Looking up String: hi id: 2 hashCode(): 146448
1
Looking up String: hi id: 3 hashCode(): 146449
2
Looking up String: hi id: 4 hashCode(): 146450
3
Looking up String: hi id: 5 hashCode(): 146451
4
1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。
通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode
4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。
以下是测试代码。
《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。
重写该方法,影响m1.equals(m2)
public boolean equals(Object o){
return true;
}
重写该方法,影响m1.hashCode()和m2.hashCode()的输出
public int hashCode(){
return 111;
}
另外,当hashCode不等的时候,向HashMap中存放值
Map map = new HashMap();
map.put(m1, m1);
map.put(m2, m2);
System.out.println(map.size());
System.out.println(map.containsKey(m1));
System.out.println(map.containsKey(m2));
会放入2个,就算equals是true
如果hashCode相等,会存放入1个
另外:设计hashcode()时最重要的因素是——无论何时,对于同一个对象调用hashcode()都应该生成同样的值。
附上一段出自Java 编程思想的代码
import java.util.*; public class CountedString { private static List<String> created = new ArrayList<String>(); private String s; private int id = 0; public CountedString(String str) { s = str; created.add(s); // id is the total number of instances // of this string in use by CountedString: for(String s2 : created) if(s2.equals(s)) id++; } public String toString() { return "String: " + s + " id: " + id + " hashCode(): " + hashCode(); } public int hashCode() { // The very simple approach: // return s.hashCode() * id; // Using Joshua Bloch's recipe: int result = 17; result = 37 * result + s.hashCode(); result = 37 * result + id; return result; } public boolean equals(Object o) { return o instanceof CountedString && s.equals(((CountedString)o).s) && id == ((CountedString)o).id; } public static void main(String[] args) { Map<CountedString,Integer> map = new HashMap<CountedString,Integer>(); CountedString[] cs = new CountedString[5]; for(int i = 0; i < cs.length; i++) { cs[i] = new CountedString("hi"); map.put(cs[i], i); // Autobox int -> Integer } System.out.println(map); for(CountedString cstring : cs) { System.out.println("Looking up " + cstring); System.out.println(map.get(cstring)); } } }
输出结果是:
{String: hi id: 4 hashCode(): 146450=3, String: hi id: 1 hashCode(): 146447=0, String: hi id: 3 hashCode(): 146449=2, String: hi id: 5 hashCode(): 146451=4, String: hi id: 2 hashCode(): 146448=1}
Looking up String: hi id: 1 hashCode(): 146447
0
Looking up String: hi id: 2 hashCode(): 146448
1
Looking up String: hi id: 3 hashCode(): 146449
2
Looking up String: hi id: 4 hashCode(): 146450
3
Looking up String: hi id: 5 hashCode(): 146451
4
相关文章推荐
- 谈谈java的"=="和equals
- java装箱和拆箱已及"=="与"equals"的区别
- [Java细节]"hi there".equals("cheers !") == true
- @suppressWarnings("unchecked")及其相关属性在Java中意思
- 关于java中JDK5的打包,拆包以及"=="和equals的问题
- Java杂谈之String----"=="与equals的区别
- Java "equals"和"=="的区别
- 对象比较: "==" "equals()" "hashCode()"
- "java.util.NoSuchElementException: No value present" 问题解决:重写hashCode 和 equals 方法
- JAVA中null,"",equals,==相互之间使用详解
- java之"equals"和"=="的区别
- Java中"=="和"equals"区别
- java hibernate 中"node to traverse cannot be null"错误解决
- JAVA 之"=="与"equals"
- "==" 和 equals的区别 java 日期Date类的使用 自动装箱和自动拆箱
- 2006-07-28 Java的常用包,"=="和"equals"的用法,基本数据类型与引用类型,对象的克隆
- Java学习,常用包,"=="和"equals",clone()
- Java中关系操作符"=="和equals()方法的用法
- Java中equals与"=="的使用区别
- Java中"equals"和"=="的区别