1. 程式人生 > >Java之路:運算子

Java之路:運算子

運算子

程式由許多語句組成,而語句組成的基本單位就是表示式與運算子。
【運算子分類】
按功能分:算術運算子、賦值運算子、關係運算符、邏輯運算子、位運算子、其他運算子。
按運算元數目:一元、二元、三元。

1、賦值運算子:=

它的意思是“取右值,把它複製給左值”。右值可以是任何常數、變數或表示式(只要它能生成一個值就行)。但左值必須是一個明確的、已命名的變數,即必須有一個物理空間可以儲存等號右邊的值。如下:

int a;
a = 4;	// 可以將常量賦給變數
//以下是錯誤
4 = a;	// 不能把任何東西賦給一個常數

注1:對基本資料型別的賦值是很簡單的,基本型別儲存了實際的值,而並非指向一個物件的引用,所以對其賦值的時候,是直接將一個地方的內容複製到了另一個地方。例如:a = b; 那麼b的內容就複製給了a。若是修改a,b並不受影響。
注2

:但是,在為物件賦值的時候,情況卻不同。對一個物件進行操作時,我們真正操作的是對物件的引用。所以,若是“將一個物件賦值給另一個物件”,實際是將“引用”從一個地方複製到另一個地方。這意味著,假如對物件使用c = d,那麼c和d都指向原本只有d指向的那個物件。如下:

class Num {
	int num;
	Num(int num){
		this.num = num;
	}
}
public class Assignment {
	public static void main(String[] args) {
		Num a = new Num(1);
		Num b = new Num
(2); System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num); a = b; // a和b都指向原來b指向的物件 System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num); a.num = 3; // 因為此時a與b是指向同一物件,所以此時改變a所指向物件的值,b所指向的結果也改變 System.out.println("a.num = " + a.num + "\t" + "b.num = " + b.num); } }

【結果】
在這裡插入圖片描述
:在許多程式語言中,我們可能會期望a,b是相互獨立的,但由於賦值運算子操作的是一個物件的引用,所以修改a的同時也改變了b!這是因為a和b包含的是相同的引用,它們指向相同的物件。(原本a包含的對物件的引用,是指向一個值為1的物件,但在對a賦值時,這個引用被覆蓋了,也即丟失了;而那個不再被引用的值為1的物件會由“垃圾回收器”自動清理。)
這種特殊的現象通常稱作“別名現象”,是Java操作物件的一種基本方式。而若要避免別名問題,則應該如下:
a.num = b.num;
這樣就可以保持兩個物件彼此獨立,而不是將a和b繫結到相同的物件。

2、算術運算子:+ - * / %


(1)整數除法會直接去掉結果的小數位,而不是四捨五入。因為整形變數無法儲存小數點後面的資料。
(2)Java中取餘運算子%的運算元可以是負數和浮點數。而在C/C++中,取餘運算子只能是整數。
(3)+運算子也可以連線兩個字串。

【示例】

public class Unary {
	public static void main(String[] args) {
		int x = 10/3;	// 取值為3,而不是3.33333...
		System.out.println("x = " + x);
		int a = 10%-3;	
		System.out.println("a = " + a);
		float b = 5.2f % 3.1f;
		System.out.println("b = " + b);
	}
}

【結果】
在這裡插入圖片描述

3、關係運算符:> < <= >= == !=

關係運算符生成的是一個boolean結果,它們計算的是運算元的之間的關係。
等於(==)和不等於(!=)適用於所有的基本資料型別。而其他比較符不適用於布林型別,因為布林型別只有true和false,大小沒有意義。

測試物件的等價性【==、!=、equals()方法】

==、!=與equals()方法

【示例】

public class Equal {
	public static void main(String[] args) {
		int m = 3;
		int n = 3;
		Integer n1 = new Integer(47);
		Integer n2 = new Integer(47);
		System.out.println(m == n);
		System.out.println(n1 == n2);
		System.out.println(n1 != n2);
	}
}

【結果】
在這裡插入圖片描述
【結果分析】
等於(==)和不等於(!=)也適用於所有的物件,但在使用時一定要注意,對於基本資料型別,它們比較的是值(基本資料型別中儲存的值)“本身”;對於引用資料型別,它們比較的變數對物件的引用(其所指向的物件在記憶體中的地址)。

(1)對於基本資料型別的變數,變數儲存的是值“本身”。而所有關係運算符比較的就是值“本身”,而

   int m = 3; 
   int n = 3;

變數n和變數m都是直接儲存的"3"這個數值,所以用==比較的時候結果是true。

(2)對於引用型別變數,引用型別的變數儲存的並不是 “值”本身,而是於其關聯的物件在記憶體中的地址。如:

	Integer n1 = new Integer(47);
	Integer n2 = new Integer(47);

引用型別變數n1中儲存的是他所指向的物件在記憶體中的地址,而不是47這個值,同理,n2也是如此。

	System.out.println(n1 == n2);

當執行上面語句時,實際上比較的是n1和n2的引用(其指向的物件在記憶體中的地址)。然而,n1和n2物件的引用卻是不同的,所以輸出false。

【equals()方法】

equals方法是基類Object中的方法,因此對於所有的繼承於Object的類都會有該方法。

equals()方法是用來比較兩個物件的引用是否相等,即是否指向同一個物件。

但equals()這個方法不適用於基本資料型別,基本型別直接使用==和!=即可。

public class Equal {
	public static void main(String[] args) {
		Integer n1 = new Integer(47);
		Integer n2 = new Integer(47);
		System.out.println(n1.equals(n2));
	}
}

【結果】

在這裡插入圖片描述
【結果分析】
不是說equals()比較的是引用嘛,那上面結果為什麼對呢?這是因為,equals()預設確實是比較引用,但是Integer類中重寫了equals()方法,使其比較引用物件的內容。
兩個引用物件的內容都是47,所以結果是true。

假設你建立了自己的類,沒有重寫equals()方法,如下:

public class Equal {
	public static void main(String[] args) {
		Value v1 = new Value();
		Value v2 = new Value();
		v1.i = 100;
		v2.i = 100;
		System.out.println(v1.equals(v2));
	}
}

【結果】
在這裡插入圖片描述
【結果分析】
這是由於equals()的預設行為是比較引用,沒有重寫equals()方法,所以它無法比較引用物件的內容,只能預設比較物件的引用,引用不同,所以結果false。

4、邏輯運算子:與(&&)、或(||)、非(!)

與、或、非操作只能運用於布林值,並返回一個布林值。

(表示式1)&&(表示式2)	// 其中表達式1和表示式2必須的結果必須是布林值
(表示式1)||(表示式2)
!(表示式)

:使用與(&&)、或(||)時,一旦能夠明確無誤地確定整個表示式的值,就不用再計算表示式餘下的部分了,這種現象被稱為“短路”。因此,整個邏輯表示式靠後的部分有可能不會被運算。

非短路:&,|
& 與 | 兩邊的表示式都要進行運算。

【分享一道Java面試題】

  1. &和&&、|和||的關係是怎麼樣?(Java面試題)
    答:
    對於“與操作”:有一個條件不滿足,結果就是false。

普通與(&):所有的判斷條件都要執行;短路與(&&):如果前面有條件已經返回了false,不再向後判斷,那麼最終結果就是false。

對於“或操作”:有一個條件滿足,結果就是true。

對於普通或(|):所有的判斷條件都要執行;

短路或(||):如果前面有條件返回了true,不再向後判斷,那麼最終結果就是true。

5、位運算子

在這裡插入圖片描述
在這裡插入圖片描述
其中,除 ~ 運算子外,其他位運算子都可以與=聯合使用。&=、|=、^=、>>=、<<=、>>>=

運算子優先順序

在這裡插入圖片描述
在這裡插入圖片描述

【一個小問題】

int i;;
int n;;;;;;;;;;;;;

上面兩條語句合法嗎?

答案是合法,事實上,由於多個Java語句可以處於同一行,那麼int i ;;就可以解讀為“int i;”這條語句和另外一個空語句“;”共處於一行之上。int i語句後面即使跟10個分號也合法。