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类型转换比较特殊,称为扩展收缩转换,分为两个步骤:
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