1. 程式人生 > >Java開發筆記(十五)短路邏輯運算的優勢

Java開發筆記(十五)短路邏輯運算的優勢

false 可見 amp 按位異或 之間 需要 進制 原因 如何

前面提到邏輯運算只能操作布爾變量,這其實是不嚴謹的,因為經過Java編程實現,會發現“&”、“|”、“^”這幾個邏輯符號竟然可以對數字進行運算。譬如下面的代碼就直接對數字分別開展了“與”、“或”、“異或”運算:

		// 3的二進制為00000011,7的二進制為00000111
		int andNumber = 3&7; // 對兩個數字進行“按位與”運算
		System.out.println("andNumber="+andNumber);
		int orNumber = 3|7; // 對兩個數字進行“按位或”運算
		System.out.println("orNumber="+orNumber);
		int xorNumber = 3^7; // 對兩個數字進行“按位異或”運算
		System.out.println("xorNumber="+xorNumber);

上述代碼也能成功編譯運行,運行結果如下所示:

andNumber=3
orNumber=7
xorNumber=4

究其原因,這三個邏輯符號原是按位邏輯運算。所謂按位邏輯,指的是先將操作數轉成二進制,再對二進制的操作數逐位進行邏輯運算,最後把每位的邏輯結果重新拼成一個二進制的運算值。例如數字3的二進制表達為00000011,數字7的二進制表達為00000111,那麽對這兩個二進制數進行“按位與”運算,得到的二進制結果為00000011即數字3;同樣對這兩個二進制數進行“按位或”運算,得到的二進制結果為00000111即數字7;繼續對這兩個二進制數進行“按位異或”運算,得到的二進制結果為00000100即數字4。
以上的實驗結果,說明了邏輯與、或、異或符號實質是按位邏輯運算,之前的布爾變量只是按位邏輯的一種運算類型。既然按位邏輯比較的是左右兩邊的各個二進制位,就意味著必須先確定左右兩邊的操作數值,然後才能對兩個操作數進行按位運算。這麽看來,按位邏輯並非真正意義上的邏輯操作,正常情況的邏輯運算應當具備下列特征:
1、只判斷真和假,不判斷0和1,更不是什麽逐位判斷;
2、對於“與”運算,一旦左邊的操作數為假,則不管右邊為何,運算結果一定為假;
3、對於“或”運算,一旦左邊的操作數為真,則不管右邊為何,運算結果一定為真;
對比發現,按位邏輯不但不符合上述的第一點特征,也不符合第二點和第三點特征,因為按位邏輯需要左右兩邊都確定之後,才能墨守成規進行邏輯運算。顯然這樣做並不經濟,倘若左邊操作數就能確定運算結果,那又何苦畫蛇添足進行右邊的冗余計算?為解決按位邏輯存在的問題,Java引入了新的短路符號來幫忙,包括短路與符號“&&”和短路或符號“||”,短路的意思是:如果左邊已經接通,那就不繞道右邊了。
話雖如此,但又如何證明短路邏輯是否真的高效呢?下面通過一個例子來分辨按位邏輯和短路邏輯之間的區別,關鍵在於邏輯符號的右邊需要修改變量值,為此引入了自增符號“++”。具體的邏輯運算代碼如下所示,主要是比較邏輯與“&”和短路與“&&”的運算結果:

		int i=1, j=1;
		// 對於按位邏輯運算,需要等待左右兩邊都計算完畢,然後進行按位邏輯判斷
		boolean result1 = 3>4 & ++i<5;
		System.out.println("result1="+result1);
		System.out.println("i="+i);
		// 對於短路邏輯運算,一旦左邊的計算能夠確定結果,就立即返回邏輯判斷的值,此時不再進行右邊的計算
		boolean result2 = 3>4 && ++j<5;
		System.out.println("result2="+result2);
		System.out.println("j="+j);

運行以上示例代碼,得到下述的運算日誌:

result1=false
i=2
result2=false
j=1

可見兩個邏輯式子的運算結果都為false,不同之處在於:“&”符號同時進行了左右兩邊的運算,所以i++執行之後i值變為2;而“&&”符號先進行左邊運算,發現3>4為假,說明與運算肯定為假,此時整個式子直接返回假,不再執行右邊的計算,於是j值仍然為1(j++未執行)。從該實驗看到,短路邏輯運算名副其實,其效率高於按位邏輯運算,因而在實際開發過程中,更經常使用短路符號“&&”和“||”進行邏輯運算,很少使用單個的“&”和“|”。

Java開發筆記(十五)短路邏輯運算的優勢