Java學習筆記——雙等號和equals的區別


一、==和equals的區別

1. ==可以用來比較基本類型和引用類型,判斷內容和內存地址

2. equals只能用來比較引用類型,它只判斷內容。該函數存在於老祖宗類 java.lang.Object

java中的數據類型,可分為兩類: 
1.基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 
  他們之間的比較,應用雙等號(==),比較的是他們的值。 
2.復合數據類型(類) 
  當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址,
  所以,除非是同一個new出來的對象,他們的比較后的結果為true,否則比較后結果為false。

  JAVA當中所有的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法。
  這個方法的初始行為是比較對象的內存地 址,但在一些類庫當中這個方法被覆蓋掉了。
  如String,Integer,Date在這些類當中equals有其自身的實現,而不再是比較類在堆內存中的存放地址了。

  對於復合數據類型之間進行equals比較,在沒有覆寫equals方法的情況下,
  他們之間的比較還是基於他們在內存中的存放位置的地址值的,
  因為Object的equals方法也是用雙等號(==)進行比較的,所以比較后的結果跟雙等號(==)的結果相同。


二、string之間的判斷

		String str1 = "hello";//存在於常量池中,堆棧
		String str4 = "hello";
		String str2 = new String("hello");//存放在堆中
		String str3 = new String("hello");
		String str5 = str2;
		
		System.out.println(str1.equals(str2));//true
		System.out.println(str3.equals(str2));//true
		System.out.println(str1==str2);//false
		System.out.println(str3==str2);//false
		System.out.println(str1==str4);//true
		System.out.println(str5==str2);//true

字符串緩沖池:程序在運行的時候會創建一個字符串緩沖池。
當使用 String str4 = "hello"; 這樣的表達是創建字符串的時候,
程序首先會在這個String緩沖池中尋找相同值的對象,
在String str1 = "hello";中,str1先被放到了池中,所以在str4被創建的時候,程序找到了具有相同值的 str1
並將str4引用s1所引用的對象"hello"

三、String可以相等的情況

		String str1 = "hello";
		String str2 = new String("hello");

		str2 = str2.intern();
		System.out.println(str1==str2);//true

		str3 = str3.intern();
		System.out.println(str3==str2);//true

(java.lang.String的intern()方法"abc".intern()方法的返回值還是字符串"abc",
表面上看起來好像這個方 法沒什么用處。
但實際上,它做了個小動作:檢查字符串池里是否存在"abc"這么一個字符串.
如果存在,就返回池里的字符串;如果不存在,該方法會 把"abc"添加到字符串池中,然后再返回它的引用。

intern遵循以下規則:對於任意兩個字符串 s 和 t,當且僅當 s.equals(t) 為 true 時,
s.intern() == t.intern() 才為 true。 

四、兩個任意實例間的判斷,比如兩個Person實例

①直接判斷

package com.test;

public class JavaTest5_Equals {
	public static void main(String[] args)  {
		A a1 = new A();
		a1.age = 10;
		a1.home = "浙江";
		A a2 = new A();
		a2.age = 10;
		a2.home = "浙江";
		System.out.println(a1==a2);
		System.out.println(a1.equals(a2));
	}
}
class A {
	int age;
	String home;
}
輸出結果為:

false
false

語句System.out.println(a1==a2);的輸出結果毫無疑問應該為 false。

按照類String的情況,語句System.out.println(a1.equals(a2));的輸出結果應該是true,但這里卻為false。

這是因為編譯器所提供的String類已經復寫了 eqauls 函數。而我們這里卻沒有進行相應的操作。

②復寫eqauls 函數

解決辦法即為重新復寫 eqauls 函數。

查閱 API 中的eqauls 函數,我們可以看到:

根據該描述,我們可以復寫類 A 中的 equals 函數

方法如下:

	//重寫父類里面的equals
	public boolean equals(Object obj)  {
		//為空false,類型不一致false,各個成員變量值相等才為true
		if(obj==null) {
			return false;
		} else {
			if(! (obj instanceof A)) {
				return false;
			} else {
				A a = (A)obj;//從泛華到具體類型需要強轉
				if(a.age==this.age && a.home.equals(this.home)) {
					return true;
				}
				return false;
			}
		}
	}


由此,我們可以重新進行判斷
package com.test;

public class JavaTest5_Equals {
	public static void main(String[] args)  {
		A a1 = new A();
		a1.age = 10;
		a1.home = "浙江";
		A a2 = new A();
		a2.age = 10;
		a2.home = "浙江";
		System.out.println(a1==a2);
		System.out.println(a1.equals(a2));
	}
}
class A {
	int age;
	String home;
	//重寫父類里面的equals
	public boolean equals(Object obj)  {
		//為空false,類型不一致false,各個成員變量值相等才為true
		if(obj==null) {
			return false;
		} else {
			if(! (obj instanceof A)) {
				return false;
			} else {
				A a = (A)obj;//從泛華到具體類型需要強轉
				if(a.age==this.age && a.home.equals(this.home)) {
					return true;
				}
				return false;
			}
		}
	}
}

執行結果為:

false
true

綜上,我們即完成了 equals 函數的復寫工作。

另:附上類String中equals函數的復寫方法:
	public boolean equals(Object anObject) {
		if (this == anObject) {
			return true;
		}
		if (anObject instanceof String) {
			String anotherString = (String) anObject;
			int n = value.length;
			if (n == anotherString.value.length) {
				char v1[] = value;
				char v2[] = anotherString.value;
				int i = 0;
				while (n-- != 0) {
					if (v1[i] != v2[i])
					return false;
					i++;
				}
				return true;
			}
		}
		return false;
	}




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM