欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

equals和==的区别

程序员文章站 2024-02-09 15:49:34
...

 有Java基础的人都会搞懂一个问题就是equals==的区别是什么.我的文章便从这开始谈起。首先我要告诉你equals==是完全一样的。你可能非常不赞同。请看下面的代码  

 public boolean equals(Object obj) {
	return (this == obj);
    }

 

显然这段代码印证了我刚才的话。那么这段代码从何而来呢,它是object类的一个方法,也就是equals的原形。至于我们所用到的equals==不一样。很简单equals被重写了。我们用到的equals方法不是Object的,而是他的子类的。当然有一个很重要的问题被我忽视了,也就是==比较的是jvm的堆中对象的位置,简单的说就是对象的地址,而不是对象的内容。

重写equals方法的类不止一个我们看看下面的这几个。

<!--EndFragment-->

 

下面看一下和==有点关系的两个代码:

      Integer i1 = 200;
  Integer i2 = 200;
  System.out.println("i1==i2: "+(i1==i2));
和
    Integer i3 = 100;
  Integer i4 = 100;
  System.out.println("i3==i4: "+(i3==i4));
  

这两代码很简单,说一句废话,如果你懂,就会感觉答案很简单,不懂,就傻眼了,哈哈。

<!--EndFragment--> 这两段代码的结果是:

 

      i1==i2: false
  i3==i4: true

 "==" 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等。
  在自动装箱时对于值从-128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,
  所以范例中,i3 与 i4实际上参考至同一个对象。
  如果超过了从-128到127之间的值,被装箱后的Integer对象并不会被重用,
  即相当于每次装箱时都新建一个 Integer对象,所以范例中,i1与i2参考的是不同的对象。
  另外,当不使用自动装箱功能的时候,情况与普通类对象一样,请看下例:

 

       Integer i3 = new Integer(100);
   Integer i4 = new Integer(100);
   System.out.println("i3==i4: "+(i3==i4));//显示false

 

<!--EndFragment--><!--EndFragment-->
 public boolean equals(Object obj) {
	if (obj instanceof Integer) {
	    return value == ((Integer)obj).intValue();
	}
	return false;
    }

 

这个方法是Integer中的方法,显然这个比较的是对象的内容,即某一Integer对象的值。而不是对象地址了。自然这个时候equals==就不一样了。

 public boolean equals(Object anObject) {
	if (this == anObject) {
	    return true;
	}
	if (anObject instanceof String) {
	    String anotherString = (String)anObject;
	    int n = count;
	    if (n == anotherString.count) {
		char v1[] = value;
		char v2[] = anotherString.value;
		int i = offset;
		int j = anotherString.offset;
		while (n-- != 0) {
		    if (v1[i++] != v2[j++])
			return false;
		}
		return true;
	    }
	}
	return false;
    }

 

这个是String中的equals方法。因此可以这样解释一下,所要判断的String对象,如果是同

一个对象,则返回true,如果不一样,但是内容一样,也会返回true

关于equals方法的重写有几条规则:

  1)自反性:对于任何非空的引用x'x.equals(x) 应该返回true

  (这也是String中重写equals时,第一个判断的原因)

  2) 对称性:对于任何引用xy,如果x.equals(y)返回true,反过来亦成立。

  3) 传递性:对于任何引用xyz,如果x.equals(y)返回

truey.equals(z)返回true,那么x.equals(z)也应该返回true

  4) 一致性:如果xy引用的对象没有发生变化,那么反复调用

x.equals(y)应该返回同样的结果。

  5) 对于任意非空引用xx.equals(null)应该返回false

下面是对重写equals方法的一些建议:

下面给出编写一个完美的equals方法的建议:

1) 显式参数命名为otherObject,稍后需要将它转换成另一个叫

做 other的变量。

2) 检测thisotherObject是否引用同一个对象:

        if (this == otherObject) return true;

        这条语句只是一个优化。实际上,这是一种经常采用的形

        式。因为计算这个等式要比一个一个地比较类中的域所付

        出的代价小得多。

3) 检测otherObject是否为null,如果为null,返回false。这项

       检测是很必要的。

                if (otherObject == null) return false;

       比较thisotherObject是否属于同一个类。如果equals的语

       义在每个子类中有所改变,就使用getClass检测:

               if (getClass() != otherObject.getClass()) return false;

       如果所有的子类都拥有统一的语义,就使用instanceof检测:

              if (! (otherObject instanceof ClassName)) retrun false;

4)将otherObject转换为相应的类类型变量:

        ClassName other = (ClassName)otherObject;

5) 现在开始对所有需要比较的域进行比较了。使用 == 比较

       基本类型域,使用equals比较对象域。如果所有的域都匹

       配,就返回ture;否则返回false

               return field1 == other.field1

                         && field2.equals(other.field2)

                         && ……;

<!--EndFragment--> <!--EndFragment-->