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

你可能感兴趣的:(java,深入解析,java,JAVA知识)