關鍵字與標識符
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