1. 程式人生 > >java-數值,物件比較---"=="和"equals"以及自動裝箱後的比較

java-數值,物件比較---"=="和"equals"以及自動裝箱後的比較

1.==: ==比較的是的地址

如果進行比較的兩個運算元都是數值型別,即使資料型別不一樣,只要他們的值相同,都能返回true;如97=='a',或者t==5.0;

如果兩個運算元是引用型別,那麼只有兩個引用變數的型別具有父子關係才可以比較,當指向同一個地址,即同一個物件的時候,才會返回true;

需要注意的地方1:

對於String類,當java程式直接使用如"hello"這種字串直接量(編譯時期就計算出來的字串值)時,JVM會使用常量池來管理這些字串;當使用new String("hello")的時候,JVM會先使用常量池管理"hello"直接量,再用String類的建構函式,new一個新的String物件;所以這裡會產生兩個物件,一個是編譯時存放在常量池的"hello"字串物件,一個是執行時new的String物件;

第一步,因為“hello”直接使用了雙引號宣告,故JVM會在執行時常量池中首先查詢有沒有該字串,有則進入第二步;沒有則直接在常量池中建立該字串,然後進入第二步。第二步:在常量池中建立了一個String物件之後,由於使用了new,JVM會在Heap(堆)中建立一個內容相同的String物件,然後返回堆中String物件的引用。該行程式碼分別在常量池和堆中生成了兩個內容相同的String物件。

需要注意的地方2:

public class Test1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s1 = "sayhello";//這裡在編譯時期就在常量池產生了一個字串常量;
		String s2 = "say";//這裡在編譯時期就在常量池產生了一個字串常量;
		String s3 = "hello";//這裡在編譯時期就在常量池產生了一個字串常量;
		String s4 = "say" + "hello";//編譯期間優化成一個字串,直接引用指向常量池裡已經產生的"sayhello"
		String s5 = s2 + s3;//s2,s3都是變數,編譯期不能確定s5是啥;用的是執行時產生在堆記憶體的s2,s3
		
		//注意的第一點已經說過了;這裡因為常量池已經有了"sayhello",所以只產生了一個物件;
		String s6 = new String("sayhello");
		
		
		System.out.println(s1==s4);//true,s1和s4都指向常量池的"sayhello",所以是一個物件,一個地址
		System.out.println(s1==s5);//false,s1指向的是常量池裡面的"sayhello",s5指向的是執行時堆記憶體中的"sayhello";
		System.out.println(s1==s6);//false,同上
	}

}

需要注意的地方3:
public class Test1 {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String s1 = "sayhello";//這裡在編譯時期就在常量池產生了一個字串常量;
		final String s2 = "say";//這裡在編譯時期就在常量池產生了一個字串常量;
		String s3 = "hello";//這裡在編譯時期就在常量池產生了一個字串常量;
		
		String s4 = s2 + "hello";//因為s2加了final 實際也是常量,
		System.out.println(s1==s4);//在編譯期能夠確定;所以s4還是引用的常量池的字串常量
	}

}



所以記住:當用雙引號宣告的String物件會在編譯期間儲存在常量池!

需要注意的地方4:

對於Integer:

public class Test2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//首先要知道這裡是自動裝箱,在編譯期間,這裡被翻譯成Integer a1 = Integer.valueOf(10);
		//然而在Integer類中,系統會把一個-128--127之間的整數自動裝箱成Integer例項,存放在一個cache陣列,
		//如果以後吧一個-128--127的整數自動裝箱成一個Integer例項,會直接指向這個陣列對於的元素;如果再這個
		//範圍之外系統會重新建立一個Integer例項,所以a3和a4是兩個不同的物件,而a1和a1都指向同一個陣列元素;
		Integer a1 = 10;
		Integer a2 = 10;
		System.out.println(a1==a2);//true
		Integer a3 = 128;
		Integer a4 = 128;
		System.out.println(a3==a4);//false
	}

}

需要注意的地方5:

String str1 = new String("S") + new String("C");        
System.out.println(str1.intern() == str1);     
System.out.println(str1 == "SC"); 

true, false
String str2 = "SEUCalvin";//新加的一行程式碼,其餘不變  
String str1 = new String("S")+ new String("C");      
System.out.println(str1.intern() == str1);   
System.out.println(str1 == "SC"); 

false,false;

str1.intern是去查詢常量池是否含有SC字串,如果有就返回常量池的引用,如果沒有就返回堆上的引用;所以第一段的第一個是true,第二個SC是放在常量池的,所以str1是堆上的,所以返回false;

第二段的話因為常量池上已經有了,所以str1.intern返回常量池上的,和堆上的不一樣;

2.equals:比較的是值,不過比較的規則是需要定義的;

首先,equals方法是object類的,object的equals規則是,只要兩個比較的物件地址一樣就算一樣,和==的比較規則是一樣的;

然而Integer,String等包裝類是重寫了equals方法的,他們的規則定義為只要兩個物件的值一樣,就算一樣;

所以,如果是自己定義的類,就需要重寫equals方法, 自己定義規則,否則就會繼承Object的equals方法的規則;

例題:

Consider the following code:
Integer s=new Integer(9);
Integer t=new Integer(9);
Long u=new Long(9);
Which test would return true?

1.(s==u) ,因為, s 是 Integer 型別, u 是 Long 型別,兩個不同型別的引用不能進行 == 比較。

2.(s==t) , s 是指向一個 9 的引用,而 t 也是一個指向 9 的引用,雖然都是指向 9 ,但卻是指向不同的 9 ,即是兩個不同的引用。因此 == 比較返回的是假。

3.(s.equals(t)) , Integer 的 equals 方法如下:

public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false ;
}
是 Integer 的例項且 value 值也相等的情況下返回真,其他返回假。
在這裡, s 和 t 都是 Integer 型別且值都為 9 ,因此結果為真。

所以如果s.equals(u),型別不一樣也會返回false;

4.(s.equals(9)) , 在進行 equals 比較之前,會對 9 呼叫 Integer.valueOf 方法,進行自動裝箱 , 由於 IntegerCache 中已經存在 9 ,所以,直接返回其引用,引用相同, equals 就自然相同了。所以結果為真。

5.(s.equals( new Integer(9)) ,直接建立了一個新的 Integer 例項,但且值也為 9 ,所以,滿足條件,返回真。

相關推薦

java-數值物件比較---"==""equals"以及自動裝箱比較

1.==: ==比較的是的地址 如果進行比較的兩個運算元都是數值型別,即使資料型別不一樣,只要他們的值相同,都能返回true;如97=='a',或者t==5.0; 如果兩個運算元是引用型別,那麼只有兩個引用變數的型別具有父子關係才可以比較,當指向同一個地址,即同一個物件的時

Java的==equals()以及自動裝箱拆箱

char AC oid name span 兩個 也會 掌握 word 拋一個問題 大家先看下面的代碼,先不要看答案自己做一下: public class AutoboxingTest { public static void main(String[] args)

Java基本資料型別的大小他們的封裝類以及自動拆箱裝箱

Java提供了一套基本資料型別,總共有八種,也會有人說是有九種。 在我們的印象中,很多人可能會說出byte,short,int,long,float,double,boolean,char這八種資料型別。 那麼還有一種是哪種呢,它到底是不是資料型別呢? 我們很容易忽略一個void,有

劍指offer66題--Java實現c++實現python實現 12.數值的整數次方

題目描述 給定一個double型別的浮點數base和int型別的整數exponent。求base的exponent次方。 C++ /* 功能測試:base=2,exponent=32 邊界測試:base=0,exponent=-1 return base!=0,expon

程式碼塊的解釋構造程式碼塊靜態程式碼塊靜態常量常量以及靜態成員變數物件成員變數的區別

12  程式碼塊 就是一塊程式碼,是一對大括號括起來的內容  方法中:限制變數的生命週期 類中 方法外: 構造程式碼塊:沒有關鍵字修飾,在每次建立物件時,在構造方法執行前進行執行 用途:可以對成員 變

[JAVA] List物件引用複製list賦值

首先,在java中沒有C語言的指標概念,但是物件傳遞預設就是引用。 如: Person person = new Person(1,"name",23);//初始化一個person Person me = person;//新建一個Person物件me,並以person初始

java課堂筆記------toString方法equals方法

引用類型 logs obj blog () str pre ava 當我 * 重寫toString方法 * 當我們需要使用當前類的toString方法時,通常我們 * 就需要重寫該方法。具體返回字符串的格式沒有嚴格 * 要求,可

Java之hashCode的作用equals方法的重構規則

ide return 一點 eset log 什麽 bsp amp person 這個是博主對hashcode的初步理解,以後加深了會再來更新: 1、hashcode是什麽? hashcode是對象的散列碼,不同的對象幾乎不一樣,說幾乎是因為還是可以一樣的。 特點:每一個對

java中正確使用hashCodeequals方法

Java 中正確使用 hashCode 和 equals 方法 轉載自:[開源中國社](http://www.oschina.net/question/82993_75533) 在這篇文章中,我將告訴大家我對hashCo

同是Java開發年薪15W50W的到底差在哪裡?

在這個IT系統動輒就是上億流量的時代,Java作為大資料時代應用最廣泛的語言,誕生了一批又一批的新技術,包括HBase、Hadoop、MQ、Netty、SpringCloud等等 。 一些獨角獸公司以及騰訊、阿里、百度、網易等知名大廠對Java人才的需求量連年升級,有2年工作經驗的優秀程式設計師

字串陣列數值物件的擴充套件

//字串 1. includes(str) : 判斷是否包含指定的字串 2. startsWith(str) : 判斷是否以指定字串開頭 3. endsWith(str) : 判斷是否以指定字串結尾 4. repeat(count) : 重複指定次數 //數值 1. 二進位制與八進位制數值表示法:

Java入門資料型別運算子總結

Java入門 1.所有的程式語言的最終目的都是提供一種“抽象”方法。抽象的層次越高,越接近人的思維。越接近人的思維,越容易使用。 2.越高階的語言越容易學習;當然,這隻意味著容易入門;不意味著成為高手越容易,高手仍然需要修煉。 3.Java的核心優勢:跨平臺。跨平臺是靠JVM(虛擬機器)實現的。 4.

劍指offer66題--Java實現c++實現python實現 15.反轉連結串列

題目描述 輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。 C++ /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/

劍指offer66題--Java實現c++實現python實現 14.連結串列中倒數第k個結點

題目描述 輸入一個連結串列,輸出該連結串列中倒數第k個結點。 C++實現 /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/

劍指offer66題--Java實現c++實現python實現 13.調整陣列順序使奇數位於偶數前面

題目描述 輸入一個整數陣列,實現一個函式來調整該陣列中數字的順序,使得所有的奇數位於陣列的前半部分,所有的偶數位於陣列的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。 C++實現 class Solution { public: void reOrderArray(v

劍指offer66題--Java實現c++實現python實現 11.二進位制中1的個數

題目描述 輸入一個整數,輸出該數二進位制表示中1的個數。其中負數用補碼錶示。 Python實現 # -*- coding:utf-8 -*- class Solution: def NumberOf1(self, n): cnt = 0 if n

劍指offer66題--Java實現c++實現python實現 29.最小的K個數

題目描述 輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。 C++ //堆排 class Solution { public: vector<int> GetLeastNumbers_Solut

劍指offer66題--Java實現c++實現python實現 28.陣列中出現次數超過一半的數字

題目描述 陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入一個長度為9的陣列{1,2,3,2,2,2,5,4,2}。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。 C++ class Solution { public:

劍指offer66題--Java實現c++實現python實現 27.字串的排列

題目描述 輸入一個字串,按字典序打印出該字串中字元的所有排列。例如輸入字串abc,則打印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。 C++ class Solution { public: vector<string> P

劍指offer66題--Java實現c++實現python實現 26.二叉搜尋樹與雙向連結串列

題目描述 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 C++ /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *ri