我的Thinking in Java學習筆記(四)
來源:互聯網
上載者:User
邏輯運算子
邏輯運算子 AND(&&)?? OR(||)? NOT(!)? 都會得到一個boolean值,且他們只能用於boolean身上。邏輯運算式中的boolean無法使用類似於c/c++中的數值代替。注意,boolean被用於一個預期會出現string的地方,其值會自動轉換為適當的文本形式,並且假如2個比較的基礎資料型別 (Elementary Data Type)不相同,也是可以比較的~例如10和10.0d,結果也是會返回true的
短路式的核定
這個的意思就是邏輯運算式中的部分語句可能因為邏輯運算子的使用不當,導致有些語句並沒有經過判斷,只要大家細心點,掌握知識牢靠就沒什麼問題~
位元運算符
位元運算符可以讓你操作整數基礎資料型別 (Elementary Data Type)中的個別bit位,切記是整數基礎資料型別 (Elementary Data Type)!位元運算符直接造作的是資料中的0和1,直接面向硬體,所以有的人說java無法控制底層硬體,這個說法是不正確的,你完全可以直接控制硬體~好象asm一樣~
位元運算符
AND(&)會在2個輸入位全為1時,產生一個輸出位1,否則為0;
OR(|)會在2個輸入位有任意一個為1時,產生一個輸出位1,當2個輸入位全部為0時,輸出0;
XOR(^)會在2個輸入位上有且只有一個輸入位為1時,產生輸出位1;
NOT(~)也叫做"一的補數運算子",是一個一元運算子(其他的是2元預算符),他僅僅接受一個引數,並且產生相反位
注意,位元運算符和邏輯運算子很想。但是他們是有區別的,我曾經見過一個招聘題目,其中就有讓你闡述他們的區別,除了’~‘之外,任何一個位元運算符都可以和賦值運算子=號合用,類似於+=
boolean,你可以在他身上執行除了not之外的任何一個位元運算符;對於boolean而言,位元運算符和邏輯運算子的唯一區別就是位元運算符不做短路式,最後boolean是無法做位移運算的
位移運算子
位移運算子也是用來操作位的,也是只能作用在整數基礎資料型別 (Elementary Data Type)上在java中採用補碼錶示位元,在補碼錶示中,最高為為符號位,正數符號位是0,負數符號位是1,補碼的規定如下:
對於正數來說,最高位是0,其餘各位代表數值本身的位元;
對於負數來說,把該數的絕對值的補碼按位取反,然後對整個數+1,取得該數的補碼。如-1的補碼為11111111,-1的絕對值補碼是00000001,按位取反11111110,再加1,11111111
左移運算子(<<)會左運算元向左遷移,遷移的位元由右運算元決定(左移後,低位補0)a=a<<2,使a的各個二進位位左移2位,右補0,若a=00001111則a<<2=00111100,高位左移後溢出的位捨棄掉了在不產生溢出的情況下,左移一位相當於乘2,用這種方法來實現乘法,要比乘法運算快很多,所以有的公司在效率題目上,會出這樣的題。
右移運算子(>>)會使左運算元向左遷移,遷移的位元由右運算元決定,面對帶有正伏負號的遷移,右移運算子先會採用一種叫符號擴充的措施:如果原值為正數,高位補0;如果原值為負數,則高位補1。
此外,java中還增加了無加號或減號的右移運算子(>>>)採用的是零擴充措施:無論原值是正還是負。一律在高位補0,如果你操作的位移對象是char 、byte、short 的話,在位移進行的時候,會把他們先提升為int,才進行位移,當然結果也是int的。位移運算中位移的位元,對於int類型的資料來說,只有低位的5個bit位是有用的,對於long來說,只是低位的6個bit位是有用的。
位移運算子和其他運算子一樣,也是可以和=號並用的,但是當在byte和short上進行無加號或減號的>>>=時候就有問題了,因為他們會先被提升為int,然後右移,再賦值回來,但是當他們賦值回來的時候,超過他們的容量大小的高位會被截去,就會產生很奇怪的數字-1
public class test
{
public static void main(String args[])
{
int i=-1;
long l=-1;
short s=-1;
byte b=-1;
i>>>=10;
System.out.println(i);//1
l>>>=10;
System.out.println(l);//2
s>>>=10;
System.out.println(s);//3
b>>>=10;
System.out.println(b);//4
b=-1;
System.out.println(b>>>10);//4
}
}
答案是?4194303、18014398509481983、-1、-1
4194303需要注意的是這個答案,因為第4個移位後的結果並沒有傳回b,所以才能顯示正確的答案,這個答案之所以和第一個是一樣的,因為b被提升成int b了,所以答案和int i的是一樣的!
if-else 三元運算子
這個好象是java中唯一的一個3元運算子,呵呵~他的格式是
boolean-exp?value1: value2
如果boolean-exp的判斷是true 則執行value1,如果為false,則執行value2,這個和if-else語句是一樣的~但是他要比
if-else語句要精練,並且執行的效率要比他高!
需要注意的是:value2中的語句是要帶有;號的,並且不能放進去System,out.println();之類的語句的,我們是用3元運算子要的是他的運算結果值,並不是if-else所能實現的控製程序流程。
逗號運算子
在java中,唯一能放;號運算子的地方,就是for迴圈中,這個我們會在以後講到應用於string身上的operator+這個問題我在我的"java初學者容易出現的運算子問題"中已經提到了~在java中,假如+號在string之前出現,執行的是運算,而要是在string 後出現,則執行的是字元串連,例如
public class test
{
public static void main(String args[])
{
int x=1,y=2,z=3;
String s="string";
System.out.println(x+y+z+s);
System.out.println(s+x+y+z);
System.out.println(x+y+s+z);
}
}
顯示6string
string123
3string3??
轉型運算子
轉型分為2類,自動轉換和強制轉換,自動轉換就是系統自動進行的寬化轉換,例如byte類型的b +1時,系統會自動把他的byte類型轉化為int類型,你可以使用byte b=b+1;看看就知道了,系統就會告訴你possible loss of precision,因為你在加1的時候,b的值已經是int類型了,你也沒辦法再賦值回b了,系統在比int小的資料類型上進行運算時會把他們的值提升為int,而在和long運算時會提升為long,以此類推。所謂的強制轉換,就是你告訴編譯器,我知道b是個int類型但是他的表達值並沒有超過byte的範圍,你就放心的轉化吧~也就是這麼一句話:b=(byte)(b+1);他就會把int縮小為byte,但是假如你運算完的值大於了原來類型表達範圍,但是你還要強制轉換,發生了記憶體溢出,那麼溢出的bit位會被拋棄,發生資料丟失現象。java中只允許除了boolean之外的基礎資料型別 (Elementary Data Type)的類型轉換,這個要記牢
字面常量
一般而言,當你將某個常量放到程式中,編譯器很清楚的知道要將他製成什麼類型,但是有的時候為了避免模糊不清,我們就可以為常量搭配一些特殊的字元,來引導編譯器的正常判斷,在常量值後添加l/L指的是long類型,添加f/F指的是float類型,d/D指的是double類型。而十六進位的表達方法是以0x/0X開頭,八進位是以0開頭,但是java中不提供二進位的表達方法,你需要注意這幾個類型所能表達的十六進位最大值
char 0xffff????? byte 0x7f??????? short? 0x7fff?? int? 0x7fffffff
java沒有sizeof運算子
再談優先順序
還是那句話,不清楚的時候加括弧~嘿嘿~也不用記那些煩瑣的優先順序了~
最後一點:當2個最夠大的int相乘時所發生的溢出而導致的異常,java是不會在編譯期或者是運行期報告的~這個應該算是他的一個小bug了~