"=="和equals方法究竟有什么区别
总结两个东西的时候,先单独把一个东西说明白了,然后说清楚另外一个。在单个描述的时候可以根据自己使用的心得把要注意的地方可以同时说出来。
== 操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。 如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals 方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码: String a=new String("foo"); String b=new String("foo"); 两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。 在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。 如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下: boolean equals(Object o){ return this==o; } 这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。 |
然而对于equels的重写应该注意一下几点:
package com.ch.test; import java.util.Date; public class MainTest { private String name; private Date birthday; public MainTest(){} public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } /* * 重写equals必须注意: * 1 自反性:对于任意的引用值x,x.equals(x)一定为true * 2 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true,y.equals(x)也一定返回true * 3 传递性:对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true, * 那么x.equals(z)也一定返 回 true * 4 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改, * 多次调用x.equals(y)要么一致地返回true,要么一致地返回false * 5 非空性:对于任意的非空引用值x,x.equals(null)一定返回false * * 请注意: * 重写equals方法后最好重写hashCode方法,否则两个等价对象可能得到不同的hashCode,这在集合框架中使用可能产生严重后果 */ /* * 1.重写equals方法修饰符必须是public,因为是重写的Object的方法. * 2.参数类型必须是Object. */ public boolean equals(Object other){ //重写equals方法,后面最好重写hashCode方法 if(this == other) //先检查是否其自反性,后比较other是否为空。这样效率高 return true; if(other == null) return false; if( !(other instanceof MainTest)) return false; final MainTest MainTest = (MainTest)other; if( !getName().equals(MainTest.getName())) return false; if( !getBirthday().equals(MainTest.getBirthday())) return false; return true; } public int hashCode(){ //hashCode主要是用来提高hash系统的查询效率。当hashCode中不进行任何操作时, //可以直接让其返回 一常数,或者不进行重写。 int result = getName().hashCode(); result = 29 * result +getBirthday().hashCode(); return result; } public static void main(String[] args) { Date dayA = new Date(4000000); MainTest a = new MainTest(); a.setName("a"); a.setBirthday(dayA); Date dayB = new Date(1000000); MainTest b = new MainTest(); b.setName("a"); b.setBirthday(dayB); Date dayC = dayA; MainTest c = new MainTest(); c.setName("a"); c.setBirthday(dayC); Date dayE = dayA; MainTest e = new MainTest(); e.setName(a.getName()); e.setBirthday(a.getBirthday()); Date dayD = dayC; TestEquel d = new TestEquel(); d.setName("a"); d.setBirthday(dayD); System.out.println(a.equals(b)); //调用自己类中所定义的equals方法 System.out.println(a.equals(a)); System.out.println(a.equals(c)); System.out.println(d.equals(a)); System.out.println(a.equals(d)); //验证重写equals的对称性 System.out.println(a.equals(e)); System.out.println(e.equals(c)); //验证重写equals的传递性 System.out.println(d.getName().equals(a.getName())); //调用Object类中equals方法 System.out.println(d.getBirthday().equals(b.getBirthday())); System.out.println("比较hanshCode的值"); /* * * 比较hashCode方法中返回的值 * 如果equals返回为true,则hashCode一定返回true。 * 如果equals返回为false,hashCode返回值不一定不相同。 * 如果hashCode返回值不同,则equals返回值一定为false。 * 如果hashCode返回值不同,则equals返回值不一定为false。 */ System.out.println(a.hashCode()); System.out.println(b.hashCode()); //如果equals返回false,则各hashCode不一定返回不同值 System.out.println(a.hashCode()== b.hashCode()); System.out.println(a.hashCode() == c.hashCode()); } }