==和equals和hashCode的理解

来源:互联网 发布:php工作流开源 编辑:程序博客网 时间:2024/05/03 07:51

      今天做面试题的时候遇到了一个问题,问题的代码如下:

      

import java.util.HashMap;import java.util.Map;public final class PhoneNumber {   private final short areaCode;   private final short prefix;   private final short lineNumber;   public PhoneNumber(int areaCode,int prefix,int lineNumber){   rangeCheck(areaCode, 999, "area code");   rangeCheck(prefix, 999, "prefix");   rangeCheck(lineNumber, 9999, "line number");   this.areaCode=(short)areaCode;   this.prefix=(short)prefix;   this.lineNumber=(short)lineNumber;   }   private static void rangeCheck(int arg,int max,String name){   if(arg<0||arg>max){   throw new IllegalArgumentException(name+":"+arg);   }   }@Overridepublic boolean equals(Object o) {  if(o==this)  return true;  if(!(o instanceof PhoneNumber))  return false;  PhoneNumber pn=(PhoneNumber) o;  return (pn.lineNumber==lineNumber)&&(pn.prefix==prefix)&&(pn.areaCode==areaCode);return false;  } public static void main(String[] args){ Map<PhoneNumber, String> m=new HashMap<PhoneNumber, String>(); PhoneNumber pn=new PhoneNumber(707,067, 5309); m.put(new PhoneNumber(707,067, 5309), "jenny"); System.out.println(m.get(new PhoneNumber(707,067, 5309))); }}   


 


       而问题就是看看程序执行完后的输出结果,我当时一看此题有个疑问但是不确定,他没有重写hashCode方法,又想起equals方法与hashCode的方法建议是一起出现的,所以想到此题有陷阱,但是又不知道什么地方有陷阱。把程序敲了一遍发现输出结果为null,猜到肯定与hashCode相关,于是在Map的put方法前加了一个端点,进入了hashmap的源码进行单步调试,我发现源码中在存取key的时候调用了hashcode方法,而默认如果不重写hashcode方法是调用的默认的hashcode,即对象的哈希码,所以不同的对象有不同的哈希码,然后他根据哈希码进行存储。当调用get方法时又根据哈希码进行取值,如果值存在才进行eqals方法的调用,所以即使equals方法返回是true也是没有用的需要重写hashCode让其返回相同的哈希码。我将代码改成如下形式后返回了jenny。

   

import java.util.HashMap;import java.util.Map;public final class PhoneNumber {   private final short areaCode;   private final short prefix;   private final short lineNumber;   public PhoneNumber(int areaCode,int prefix,int lineNumber){   rangeCheck(areaCode, 999, "area code");   rangeCheck(prefix, 999, "prefix");   rangeCheck(lineNumber, 9999, "line number");   this.areaCode=(short)areaCode;   this.prefix=(short)prefix;   this.lineNumber=(short)lineNumber;   }   private static void rangeCheck(int arg,int max,String name){   if(arg<0||arg>max){   throw new IllegalArgumentException(name+":"+arg);   }   }@Overridepublic boolean equals(Object o) {  if(o==this)  return true;  if(!(o instanceof PhoneNumber))  return false;  PhoneNumber pn=(PhoneNumber) o;  return (pn.lineNumber==lineNumber)&&(pn.prefix==prefix)&&(pn.areaCode==areaCode);return false;  }@Overridepublic int hashCode(){return 7*(new Integer(lineNumber).hashCode())+11*(new Integer(prefix)).hashCode()+13*(new Integer(areaCode).hashCode());} public static void main(String[] args){ Map<PhoneNumber, String> m=new HashMap<PhoneNumber, String>(); PhoneNumber pn=new PhoneNumber(707,067, 5309); m.put(new PhoneNumber(707,067, 5309), "jenny"); System.out.println(m.get(new PhoneNumber(707,067, 5309))); System.out.println(pn.getClass()); }}      



 

现在说一下equals方法和==的区别,==默认是比较两个对象的引用是否相等,equsls如果没被重写默认也是按照==进行比较。==一般用来比较两个基本类型是否相等,我们在比较字符串相等的时候也用equals方法,那是因为在String类中已经将equals方法和hashCode方法进行了覆写,比较的是值的大小。

原创粉丝点击