Java深入解析筆記

關鍵字與標識符

goto、const、true、false、null
goto是Java裏的保留字(不使用的關鍵字),在java裏使用標籤實現跳轉:

public class Test1{
    public static void main(String[] args) {
        int[][] arr = {
                {1,20,28},
                {26,50},
                {33,55,66,88}
        };
        int number = 0;
        outer:
        for (int i = 0;i < arr.length; i++ ) {
            for (int j = 0; j < arr[i].length ; j++) {
                System.out.println(arr[i][j]);
                number++;
                if (number == 5) {
                    break outer;//java裏使用標籤 替代goto
                }
            }
        }
    }
}

與goto類似,const也是保留字,而true、fasle、null不是關鍵字,但是卻不能作爲標識符使用!
標識符
組成標識符的字母不再侷限於26個英文字母而是Unicode字符集(U+0000~U+10FFFF),可以使用Character類裏的下列方法判斷標識符的合法性:

//判斷字符是否是合法的標識符首字符
public static boolean isJavaIdentifierStart(int codePoint)
//判斷字符是否是合法的標識符字符
public static boolean isJavaIdentifierPart(int codePoint) 

//內部調用的是isJavaIdentifierStart(int codePoint)
public static boolean isJavaIdentifierStart(char ch)
//內部調用的是 isJavaIdentifierPart(int codePoint) 
public static boolean isJavaIdentifierPart(char ch)
public class Test2 {
    public static void main(String[] args) {
        int start = 0;
        int part = 0;
        //Unicode範圍u+0000~u+10FFFF
        for (int i = 0x0000; i < 0x10ffff; i++) {
            if (Character.isJavaIdentifierStart(i)){
                start++;
            }
            if (Character.isJavaIdentifierPart(i)){
                part++;
            }
        }
        System.out.println("Unicode字符集個數:" + (0x10ffff + 1));
        System.out.println("可以作爲標識符首字符的個數:" + start);
        System.out.println("可以作爲標識符的一部分的個數:" + part);
        System.out.println("二者之差:" + (part - start));
    }
}

運行結果:

Unicode字符集個數:1114112
可以作爲標識符首字符的個數:101296
可以作爲標識符的一部分的個數:103584
二者之差:2288

Unicode最初設計是固定的16位字符編碼,範圍是U+0000 ~ U+FFFF被稱爲基本多語言面(BMP),java中使用char類型表示,隨着Unicode的不斷擴展,已經超出了這個範圍,目前有效範圍是U+0000 ~ U+10FFFF, 超出的部分U+10000 ~ U+10FFFF被稱爲增補字符,這部分不能用char來表示,而要使用代理對錶示:

public class Test3 {
    public static void main(String[] args) {
      int codePoint = 0x28e16;
      //將 代碼點 轉換成字符數組,取得 代理對 編碼值
        char[] chars = Character.toChars(codePoint);
        String s = String.valueOf(chars);
        System.out.println("增補字符爲:" + s);
        System.out.println("String長度:" + s.length());
        System.out.println("String代碼點的數量:" + s.codePointCount(0, s.length()));
        System.out.println("高代理字符編碼值:U+" + Integer.toHexString(chars[0]));
        System.out.println("低代理字符編碼值:U+" + Integer.toHexString(chars[1]));
        //通過代理對獲得代碼點
        int codePoint2 = Character.toCodePoint(chars[0], chars[1]);
        System.out.println("代碼點:" + Integer.toHexString(codePoint2));
    }
}

運行結果:

增補字符爲:?
String長度:2
String代碼點的數量:1
高代理字符編碼值:U+d863
低代理字符編碼值:U+de16
代碼點:28e16

表示“?”字,用'\u28e16'肯定不行,而要表示成"\ud863\ude16" 代理對的取值區間是U+D800 ~ U+DFFF,該區域沒有分配字符。
Unicode轉義處理時期是在編譯器將程序解析成各種符號之前進行的,如果\u後面沒有接4個十六進制數字,將會產生編譯錯誤,就算是在註釋中也不例外!
整型轉換
byte類型到char類型轉換比較特殊,稱爲擴展收縮轉換,分爲兩個步驟:

  • 將byte通過擴展轉換,轉換成int類型
  • 再將int類型通過收縮轉換,轉換成char類型
public class Test5 {
    public static void main(String[] args) {
        byte b1 = 10;
        byte b2 = -10;
        char c1 = (char) b1;
        char c2 = (char) b2;
        System.out.println(c1 + 0);//轉爲int以便輸出
        System.out.println(c2 + 0);
    }
}

運行結果:

10
65526

先分析byte值爲10的轉換,其二進制爲0000 1010,計算機裏存放的都是對應補碼,正數的補碼是其本身,其補碼:

0000  1010

轉換爲char的第一個步驟,擴展爲int類型,執行符號擴展,因爲是正數,所以高位補0:

0000 0000 0000 0000 0000 0000 0000 1010

第二個步驟,將int收縮轉換爲char,直接截取低16位:

0000 0000 0000 1010

最終轉爲int輸出0000 0000 0000 0000 0000 0000 0000 1010,其值還是10。
然後分析byte值爲-10的轉換過程,-10的原碼1000 1010,其補碼1111 0110(符號位不變其他取反,然後加1):
轉換char的步驟一,byte轉爲int,執行符號擴展,高位補1(因爲符號位是1)

1111 1111 1111 1111 1111 1111 1111 0110

步驟二,截取低16位:

1111 1111 1111 0110

最終換位int輸出,因char是無符號類型,所以高位補0 0000 0000 0000 0000 1111 1111 1111 0110,其值爲65526
注意:char是無符號類型,最高爲依然是其有效數字而不是符號位!
浮點類型
二進制大多不能精確的表示小數,所以浮點數在計算機中只是近似存儲,如:

   float f1 = 0.1f;
   float f2 = 0.2f;
   System.out.println(f1 + f2);
   //0.30000000149011613
for(float f = 0.1f; f != 1; f += 0.1f){
	...
}
//實際上是個死循環
 //如果數量級差別很大 計算會有偏差
 float f3 = 30000000;
 float f4 = f3 + 1;
 System.out.println("f3 = " + f3 + ", f4 = " + f4);
 System.out.println(f3 < f4);

 //f3 = 3.0E7, f4 = 3.0E7
 //false

浮點數與整形的轉換
整形轉浮點型雖然是擴展轉換,但是如果其範圍超出了浮點型的有效數字範圍(float7 ~ 8個有效數字 double15 ~ 16個),就會採用IEEE754最近舍入模式,提取與該整型最接近的浮點值,就會有精度損失:

public class Test7 {
    public static void main(String[] args) {
        int a = 7654321;
        int b = 987654321;
        float a1 = a;
        float b1 = b;
        System.out.println(a1);
        System.out.println(b1);
    }
}
7654321.0
9.8765434E8
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章