equals和==

    1.“==”等号操作是什么

       “==”或等号操作在Java编程语言中是一个二元操作符,用于比较原生类型和对象。就原生类型如boolean、int、float来说,使用“==”来比较两者,这个很好掌握。但是在比较对象的时候,就会与equals()造成困惑。“==”对比两个对象基于内存引           用,如果两个对象的引用完全相同(指向同一个对象)时,“==”操作将返回true,否则返回false。(一般用于原生态,用于对象比较时,只要对象内存引用相同即可!)

 

 

   2.什么是equals方法

         equals()方法定义在Object类里面,根据具体的业务逻辑来定义该方法,用于检查两个对象的相等性。默认的equals方法实现是与“==”操作一样的,基于业务需求重写equals方法是最好的实践之一。

       但:

        JDK类中有一些类覆盖了oject类的equals()方法,这些类有:java.io.file,java.util.Date,java.lang.string,包装类(Integer,Double等),这时候:

       equals比较的是值是否相同,而不是对象内存引用是否相同。

       (equals默认和==比较对象相同,但在file,Date,String,包装类时,equals比较的是内容!)

   3.区别:

     字符串的==和equals对比

      字符串的比较是一个常见的情景,因为java.lang.String类重写了equals方法,它返回true如果两个字符串对象包含有相同的内容,但是==只有他们的引用地址相同时才返回true,下面这个例子就是通过==和equals方法分别比较两个字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String personalLoan = new String( "cheap personal loans" );
String homeLoan = new String( "cheap personal loans" );
 
//since two strings are different object result should be false
boolean result = personalLoan == homeLoan;
System.out.println( "Comparing two strings with == operator: " + result);
 
//since strings contains same content , equals() should return true
result = personalLoan.equals(homeLoan);
System.out.println( "Comparing two Strings with same content using equals method: " + result);
 
homeLoan = personalLoan;
//since both homeLoan and personalLoand reference variable are pointing to same object
//"==" should return true
result = (personalLoan == homeLoan);
System.out.println( "Comparing two reference pointing to same String with == operator: " + result);
 
Output:
Comparing two strings with == operator: false
Comparing two Strings with same content using equals method: true
Comparing two reference pointing to same String with == operator: true

      ==与equals在对象之间的对比
      另一中情景是:当你对比两个对象时,在选择==和equals方法中很容易困惑,当你比较的两个引用指向的对象是Object的类型的时候,那么你看到的结果和==是一致的,因为默认的equals方法实现仅仅比较的内存地址。如果两个引用变量完全指向的         是同一个对象的话就返回true,下面这个例子是equals和==方法操作比较的是两个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Object obj1 = new Object();
Object obj2 = new Object();
 
// == should return false
result = (obj1==obj2);
System.out.println( "Comparing two different Objects with == operator: " + result);
 
//equals should return false because obj1 and obj2 are different
result = obj1.equals(obj2);
System.out.println( "Comparing two different Objects with equals() method: " + result);
 
// "==" should return true because both obj1 and obj2 points same object
obj1=obj2;
result = (obj1==obj2);
System.out.println( "Comparing two reference pointing to same Object with == operator: " + result);
 
Output:
Comparing two different Objects with == operator: false
Comparing two different Objects with equals() method: false
Comparing two reference pointing to same Object with == operator: true

  再来看一下String这个特殊类:

  (1)String ok1=new String(“ok”);

   (2)String ok2=“ok”;
    我相信很多人都知道这两种方式定义字符串,但他们之间的差别又有多少人清楚呢。画出这两个字符串的内存示意图:


      String ok1=new String(“ok”)。首先会在堆内存申请一块内存存储字符串ok,ok1指向其内存块对象。同时还会检查字符串常量池中是否含有ok字符串, 若没有则添加ok到字符串常量池中。所以 new String()可能会创建两个对象.
     String ok2=“ok”。 先检查字符串常量池中是否含有ok字符串,如果有则直接指向, 没有则在字符串常量池添加ok字符串并指向它. 所以这种方法最多创建一个对象,有可能不创建对象
     所以 String ok1=new String(“ok”);//创建了两个对象
             String ok2=“ok”;//没有创建对象
   理解下面这个demo:
   
package string;

public class TestString {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String  str1 = new String("lopez");//创建了两个对象
		String str2 = "lopez";//没有创建对象
		System.out.println(str1.equals(str2));//String覆盖了Object的equals方法,String的equals比较值,而Object比较两个引用变量是否指向同一个对象,true
		System.out.println(str1 == str2);//false
		
		//常量池在java用于保存在编译期已确定的,s1和s2在编译期已确认
		String s1 = "lopez1";
		String s2 = "lopez" + 1;
		System.out.println(s1 == s2);//true
		
		//s4在编译期还没有确认()
		String s3 = "lopez1";
		int i = 1;
		String s4 = "lopez" + i;
		System.out.println(s3 == s4);//false
		
		//一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码(false)
		String s5 = "lopez1";
		final String s = "1";
		String  s6 = "lopez" + s;
		System.out.println(s5 == s6);//true
		
		//static需要初始化的时候才能确定值,而不是在编译期确定
		String s8 = "lopez1";
		String  s9 = "lopez" + ss;
		System.out.println(s8 == s9);//false
		
		//包装类
		Integer in1 = new Integer(1);
		Integer in2 = new Integer(1);
		System.out.println(in1 == in2);//false
		System.out.println(in1.equals(in2));//true
	}
	static String ss = "1";

}
   参考链接:http://liqita.iteye.com/blog/1463856
                    http://longpo.iteye.com/blog/2199493
 
   补充:提供等值方法:
   
  • 等值方法一 ── equals(Object o) 方法

    equals 方法实现了一个等价关系:

    • 自反性 : 对于任何对象 x, x.equals(x) 必须返回 true;
    • 对称性 : 对于任何对象 x 和 y, x.equals(y)==true 当切仅当 y.equals(x)==true;
    • 传递性 : 对于任何对象 x,y,z,如果 x.equals(y)==true 和 y.equals(z)==true, 则 x.equals(z)==true;
    • 一致性 : 对于任何对象 x 和 y,只要没有对 x,y 进行修改,多次的 x.equals(y) 调用应该返回相同的值;
    • 对于任何 non-null 对象 x, x.equals(null)==false。

    Object 类中这个方法被实现为严格相等,也就是如果比较的两个对象是同一对象,即 == 操作为 true,则返回 true。所以如果想在集合中搜索内容相等的成员对象或在 map 中获取内容相等的键映射的值,成员对象(或键对象)的类必须覆盖 equals(Object o) 方法。

 

    

猜你喜欢

转载自lopez.iteye.com/blog/2218581