Java解惑讀書筆記1 – JAVA編程語言程序開發技術文章

1。奇偶判斷,應該用i%2!=0為奇數來判斷,因為當為負數的時候%2的結果可能會是-1,用i%2==1會出錯。(i&1)!=0使用低位是否為1來判斷是否奇偶。


2。小數精確計算。java中的float和double都是不太精確的,容易造成精度丟失,比如System.out.println(2.00-1.10);結果不是0.9而是0.8999999999999999。一次我們可以用long或者int來代替浮點數(比如0.9我們可以用200-110表示來計算,最後結果除以100.0F)。或者使用BigDecimal


3.int 相乘溢出!這個最常見瞭,在項目中經常出現多少天等於多少毫秒之類的,如果這樣算long s =  25 * 24 * 3600 * 1000,最後s=-2134967296,怎麼會溢出呢,原因是這幾個都是整形,最大值是2147483647,所以25天就溢出瞭而24天是正常的,怎麼辦?把25改為25L即可,它會強制轉化為long型再計算,如果我把1000改為1000L,像這樣long s =  25 * 24 * 3600 * 1000L,可能會溢出嗎?還是會,如果前面的數字超出整形就溢出,所以應該把左邊的第一個數設置為long型。


4.字面常量,所以的字面常量都是int型,不管是10進制還是16進制,除非以L結尾表示他是long型。


5.窄數字拓展到寬數字的拓展。如果是char類型,一定是無符號拓展,因為char沒有負數。其他的,如果之前是正數則無符號拓展,如果是負數則有符號拓展。記住這點即可。

6.這個和上面的相似。(byte)0x90 == 0x90 嗎?不等於,因為左邊的會被拓展成int,而byte這個是負數,會有符號拓展,最後結果是負數和0x90當然不相等,可以加一個掩碼0xFF把前面的負數去除即可 (byte)0x90 & 0xFF == 0x90,

按位與0xFF的意思是隻保留數字的低8位,高位按0處理。


7.三元表達式(:?)。討論起表達式的值,a?b:c這樣的,如果b或者c一個是int或者long字面常量,而另一個是char byte short等變量,則表達式類型為char byte short。如果沒有一個是字面常量,則拓展為最寬的作為表達式類型。舉例
Java代碼 
char x = 'X'; 
int i = 65; 
System.out.println(true ? x : 65);// X 
System.out.println(false ? x : 65);// A。註意這裡不是65 
System.out.println(true ? i : x);// 65 
System.out.println(false ? i : x);// 88。註意這裡不是X 


8.+=符合運算。x+=i和x=x+i是不等效的,因為會涉及到類型的轉化。如果x是窄的,i是寬的,x+=i編譯不報錯但結果可能會溢出,而x=x+i則編譯不通過。所以盡量不要在復合運算左邊用byte char short類型,容易溢出。舉例。
Java代碼 
int i=10033333; 
byte b = 12; 
//編譯無措,結果會溢出 
b += i; 
//編譯錯誤 :cannot convert from int to byte 
//b = b + i; 


9.++i和i++區別,這個一般人都知道,不說瞭

10.Integer.MAX_VALUE+1=Integer.MIN_VALUE。因為int是有符號數,最大值為0x7FFFFFFF,+1變為0x80000000,這個是負數最小值。這樣看int好像是一個循環,超過最大值便成瞭最小值瞭。

11。移位.x<<y。如果x是byte,char ,short會被拓展為int再移位,怎麼拓展參照前面介紹的拓展方法,如果y超過32會取對32的模,也就是說最多隻能移32位,如果x是long型,則y會對64取模。舉例
Java代碼 
System.out.println(-1 << 31);// -2147483648 向左移31%32=31位 
System.out.println(-1 << 32);// -1 向左移32%32=0位 
System.out.println(-1 << 33);// -2 向左移33%32=1位 
System.out.println(-1 << 1);// -2 向左移1%32=1位 
 
System.out.println(-1L << 63);// -9223372036854775808 向左移63%64=63位 
System.out.println(-1L << 64);// -1 向左移64%64=0位 
System.out.println(-1L << 65);// -2 向左移65%64=1位 

 

12。double和float有正無窮大和負無窮大的定義,所以double d = 1.0/0.0;這是可以編譯和運行的(int和long不行),結果d為Double.POSITIVE_INFINITY。而Double.POSITIVE_INFINITY + 1 == Double.POSITIVE_INFINITY。還有一個Double.NEGATIVE_INFINITY表示負無窮大。

13.double和float有個NaN,它不等於任何數字,包括自己,double d = 0.0/0.0,d即Double.NaN

14.自動拆箱,這個最常見瞭,目前1.6版本支持。
Java代碼 
// 為瞭兼容以前版本,1.5不會自動拆箱 
System.out.println(new Integer(0) == new Integer(0));// false 
// 1.4編譯非法,1.5會自動拆箱 
System.out.println(new Integer(0) == 0);// true 


15.為什麼-0x00000000==0x00000000、-0x80000000== 0x80000000.隻需要知道,最高位為符號位,0表示整數,1表示負數。內存中是補碼表示所有數字的,正數的補碼就是其二進制碼,而負數的補碼需要計算,計算方法:將其絕對值按位取反。然後+1即可。舉例。-0x80000000的絕對值為0x80000000,按位取反為0x7FFFFFFF,然後加1等於0x80000000,所以-0x80000000== 0x80000000。

16.Math.abs可能會負數,System.out.println(Math.abs
(Integer.MIN_VALUE));// -2147483648。原因可以abs計算方法:return (a<0)?-a:a,可參照15,知道Integer.Min_VALUE == -Integer.MIN_VALUE.同理Long也類似.

17。不要使用基於減法的比較器。為何?可能會溢出啊,比如
int x = -2000000000;
int y = 2000000000;
顯然x是小於y的,如果按照x-y>0來判斷,x-y最後是正的,結果就錯瞭。
可使用比較型,如
基於整型的比較器的實現一般使用如下的方式來比較:
Java代碼 
public int compare(Integer i1, Integer i2) { 
    return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1)); 


18. int i=-2147483648與int i=-(2147483648)?
前面的式子可以編譯通過,後面的編譯不通過,為啥,因為int型字面常量,最大值為2147483647.所以int i=-(2147483647)就可以瞭。


小結:前面這個18個問題都是數值表達式方面的,在平時使用的時候,隻要註意別溢出即可。

 

本文出自“kodak-zhou”

發佈留言