《Java核心技术 卷一》 读书笔记 第三章

   Java的基本程序设计结构

   Java中,长整型数值有一个后缀L或l(如400000000L)。十六进制数值有一个前缀0x或0X(如0xCAFE)。八进制有一个前缀0,比如010对应十进制中的8。建议最好不要使用八进制常数。

 

    从Java7开始,加上前缀0b或0B就可以写二进制数。比如0b1001就是9。还可以为数字加上下划线,比如1_000_000表示100万,只是为了让人更易读。Java编译器会去除这些下划线。

    浮点值不适用于无法接受舍入误差的金融计算。比如2.0-1.1输出的是0.8999999999,而不是0.9。这种误差的原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数1/10。

  类常量

    在Java中,经常希望某个常量可以在一个类的多个方法中使用,通常将这些常量称为类常量可以使用关键字static final设置一个类常量。类常量的定义位于main方法的外部。

    关键词final表示这个变量只能被赋值一次。一旦被赋值后就不能够再更改了。习惯上常量名使用全大写。

public class HelloJava {
    public static final double PI=3.14;//定义一个类常量
	public static void main(String[] args) {
		double width=8.5;
		System.out.print(PI*width);
	}
}

二元运算符数值类型转换

   当使用二元运算符连接两个值时(例如n+f),要先将两个操作数转换为同一种类型,然后进行计算。

   如果两个操作数中有一个是double类型,另一个操作数就会转换为double类型。

   如果两个操作数中有一个是float类型,另一个操作数就会转换为float类型。

   如果两个操作数中有一个是long类型,另一个操作数就会转换为long类型。

   否则,两个操作数都将转换为int类型。

      如果第一个操作数已经能够确定表达式的值,第二个操作数就不必计算了。(比如A&&B,如果A为假,那整个式子一定为假,B就不用计算了。同理,A||B,如果A为真,那也不用计算B了,因为式子一定为真)

 将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串。

public class HelloJava {
	public static void main(String[] args) {
		int age=13;
        String rating="PG"+age;//age转化成字符串
		System.out.print(rating);
	}
}

码点与代码单元

   char数据类型是一个采用UTF-16编码表示Unicode码点代码单元。最常用的Unicode字符使用一个代码单元就可以表示(a,b,c等),而辅助字符(𝕆等)需要两个代码单元表示。

    码点:是指一个编码表中的某个字符对应的代码值。(也就是字符在Unicode表中的位置

    在Java中一个Unicode占2个字节(byte),一个字节等于8比特位(bit),因此,每个Unicode码占用16个比特位。若一个字符的代码长度为16位,则为一个代码单元。若一个字符的代码长度有两个16的代码长度编码,则该字符有两个代码单元。

    获取方法:

    String.length():返回字符串代码单元的个数。

    String.codePointCount(int startIndex,int endIndex):返回startInde到endIndex-1之间的码点个数。(也就是有多少个字符,因为一个字符对应一个位置(代码值))

     String.charAt(int index):返回给定位置的代码单元,尽可能不要调用这个方法。

     String.codePointAt(int index):返回给定位置的码点(也就是该字符在Unicode中的位置)

     String.offsetByCodePoints(int startIndex,int cpCount):返回从stratIndex码点开始,cpCount个码点后的码点索引。

     举例:hi𝕆  这个字符串实际上有三个码点,四个代码单元。

 1.测试length函数和codePointCount函数

public class HelloJava {
	public static void main(String[] args) {
		String greeting="hi𝕆";
		int t=greeting.length();
		int h=greeting.codePointCount(0, t);
		System.out.println(t);
		System.out.println(h);
	}
}

  首先测试的是测量字符串长度的两种方法——用length方法得出字符串代码单元个数为4,因为𝕆这个符号是由两个代码单元得到的。而用count方法得出字符串码点个数为3,也就是有多少个字符。

 2.测试charAt函数

public class HelloJava {
	public static void main(String[] args) {
		String greeting="hi𝕆";
		char a=greeting.charAt(0);
		char b=greeting.charAt(1);
		char c=greeting.charAt(2);
		char d=greeting.charAt(3);
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);	
	}
}

    由于charAt函数是返回给定位置的代码单元,因此在第2个和第三个位置返回的是相同的代码单元。charAt可以在没有辅助元素的字符串中使用。

 3.测试codePointAt函数

public class HelloJava {
	public static void main(String[] args) {
		String greeting="hi𝕆";
		int a=greeting.codePointAt(0);
		int b=greeting.codePointAt(1);
		int c=greeting.codePointAt(2);
		int d=greeting.codePointAt(3);
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
	}
}

 codePointAt函数返回的是序号对应的字符在Unicode表中的位置,可以看出h和i位置是挨在一起的,并且𝕆符号是由两个不同代码单元组成的。

4.测试offsetByCodePoints函数

public class HelloJava {
	public static void main(String[] args) {
		String greeting="hi𝕆";
		int a=greeting.offsetByCodePoints(0, 0);
		int b=greeting.offsetByCodePoints(0, 1);
		int c=greeting.offsetByCodePoints(0, 2);
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
	}
}

    经过的是码点数而不是代码单元,因此这个就可以看作是从序号为startIndex开始,经过cpCount个位置,对应的码点的序号。与代码单元就没有关系了。

    总结:

    String.codePointCount(int startIndex,int endIndex) 是最标准的求字符串长度的函数

int cpCount = String.codePointCount(0,String.length());

    String.codePointAt(int index)   是最标准的求码点在Unicode位置的函数

    String.offsetByCodePoints(int startIndex,int cpCount)  是最标准的求码点对应序号的函数

    想要得到第i个码点,应该使用下列语句

int index = String.offsetByCodePoints(0,i);
int cp = String.codePointAt(index); 

构建字符串

   当需要用字符串构建字符串的时候,使用拼接效率会很低,每次拼接字符串时,都会构建一个String对象,既耗时,又浪费空间。因此使用StringBuilder类

   构建一个空的字符串构建器:

      StringBuilder builder=new StringBuilder();

  其中builder是构建器的名字。

  当每次需要添加一部分时,就调用append方法:

		builder.append("Hello,");
		builder.append("World!");

  在字符串构建完成后,调用toString方法,得到一个String对象:

		String s=builder.toString();
public class HelloJava {
	public static void main(String[] args) {
		StringBuilder builder=new StringBuilder();
		builder.append("Hello,");
		builder.append("World!");
		String s=builder.toString();
		System.out.print(s);
	}
}

Java的输入

     输出很简单,使用System.out.println即可,但是要想通过控制台进行输入,则需要构造一个与“标准输入流” System.in 关联的Scanner对象。构造之后,就可以使用Scanner类的各种方法读取输入了。

import java.util.*;
public class HelloJava {
	public static void main(String[] args) {
		Scanner in =new Scanner(System.in);//构造Scanne对象
		System.out.print("What is your name?");
		String name=in.nextLine();//读取一行输入
		System.out.println("Hello, "+name);
		System.out.print("How old are you?");//读取一个整数
		int age=in.nextInt();
		System.out.println(age);
	}
}

 当使用的类不是定义在基本包java.lang中时,一定要使用import导入相应的包。

 在标准化输出中,System.out.printf也可以用C语言的语法。

import java.util.*;
public class HelloJava {
	public static void main(String[] args) {
		Scanner in =new Scanner(System.in);//构造Scanne对象
		System.out.print("What is your name?");
		String name=in.nextLine();//读取一行输入
		System.out.printf("你的名字是%s",name);
	}
}

   不能在嵌套的两个块中声明同名的变量。(在C++中,可以在嵌套的块中重定义一个变量。在内层定义的变量会覆盖在外层定义的变量。但Java不允许这样做)

带标签的break

     虽然在Java中并不会使用goto语句,但是设计者还是增加了一个与goto类似的语法——带标签的break,用于跳出多重嵌套的循环语句。标签必须放在希望跳出的最外层循环之外,并且必须紧跟一个冒号。

public class HelloJava {
	public static void main(String[] args) {
		int n=10,i=0;
		read_data://标签
			while(i<n) {
				for(int j=0;j<20;j++) {
					i++;
					if(i==8)
						break read_data;//标签break的语法
				}
				i++;
			}
		System.out.print(i);
	}
}

  如果没有提前退出,i的结果应该是10,而现在为8。

  同理,continue也有带标签的continue,语法与break相同。

  大数

   java.math包中有两个很有用的类:BigInteger和BighDecimal这两个类可以处理包含任意长度数字序列的数值。BigInteger类实现任意精度的整数运算,BigDecimal实现任意精度的浮点数运算。

   使用valueOf方法可以将普通的数值转换为大数

		BigInteger a=BigInteger.valueOf(100);

  不能使用人们熟悉的算术运算符(如+和*)来处理大数,而需要使用大数类中的add,subtract,divide,mutiply等方法。(注意方法传入的参数也必须是大数,不能是具体的数字

import java.math.*;
public class HelloJava {
	public static void main(String[] args) {
		BigInteger a=BigInteger.valueOf(100);
		BigInteger b=BigInteger.valueOf(20);
		BigDecimal c=BigDecimal.valueOf(100.222);
		BigDecimal d=BigDecimal.valueOf(20.222);//静态方法构造大数
		BigInteger e=a.add(b);
		BigDecimal f=c.multiply(d);
		System.out.println(e);
		System.out.println(f);
	}
}

 需要注意的是BigDecimal的divide方法,如果商是一个无限循环小数,那么就需要传入第二个参数RoundingMode,用于对无限循环小数的操作。比如RoundingMode.HALF_UP就是四舍五入。

import java.math.*;
public class HelloJava {
	public static void main(String[] args) {
		BigDecimal c=BigDecimal.valueOf(100.222);
		BigDecimal d=BigDecimal.valueOf(20.222);
		BigDecimal f=c.divide(d,RoundingMode.HALF_UP);//divide的第二种写法
		System.out.println(f);
	}
}

声明数组

   Java的声明数组有两种方法——int[] a 和 int a[],大多数程序员喜欢用第一种,因为它可以将类型int[](整型数组)与变量名清晰地分开。

  同时Java中要给数组分配空间,使用的语法是

int[] a = new int[100];

 注意与C++不同,没有int a[100]的方式。分配空间一定要用new。

 当然也可以对数组进行初始化

int[] a = {2,3,5,7,11};

for each循环

    这是一种功能很强的循环结构,可以用来一次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下标值。 这个循环将会遍历数组中的每个元素,而不是下标值。

     语法格式:for(variable:collection){}   其中variable表示暂存数组元素的变量名,collection表示一个数组(或实现了Iterable接口的类对象)

public class HelloJava {
	public static void main(String[] args) {
		int[] a= {1,2,3,4,5,6,7};
		for(int t:a) {
			System.out.println(t);
		}
	}
}

   在Java种,允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组——因为Java中的数组名实际上相当于一个数组指针。(int* a = new int[100])

public class HelloJava {
	public static void main(String[] args) {
		int[] a= {1,2,3,4,5,6,7};
		int[] b= a;
		b[1]=99;//数组a同样也会发生变化
		for(int t:a) {
			System.out.println(t);
		}
	}
}

    发现改变数组b的同时,a也发生了变化。

    如果需要对二维数组使用for each循环语句,那么需要使用两个嵌套的循环——for each不能自动处理二维数组的每个元素。需要先处理行,再处理行中的元素

public class HelloJava {
	public static void main(String[] args) {
		int [][] a = new int[20][20];//声明二维数组的方法
		int [][] b = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};//二维数组初始化的方法
		for(int[] row:b) {//用row处理每一行
			for(int value:row) {//用value处理行中的元素
				System.out.print(value+" ");
			}
		}
	}
}

   在二维数组中,a[i]表示第i个子数组,也就是第i行,它本身也是一个数组。而a[i][j]则是引用这个数组的第j个元素(准确的说是序号为j的元素)。

    在Java中,可以让两行进行交换。

public class HelloJava {
	public static void main(String[] args) {
		int [][] b = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};//二维数组初始化的方法
		int []temp = b[0];
		b[0] = b[1];
		b[1] = temp;
		for(int[] row:b) {
			for(int value:row) {
				System.out.print(value+" ");
			}
		}
	}
}

 

对Java二维数组的详细解释

double [][] a = new double[10][6];//声明二维数组并分配空间

  在C++中,这句代码并不同于 double a[10][6],也不同于 double (*a)[6] = new a[10][6] 而是分配了一个包含十个指针的数组。

double** a = new a*[10];

  然后,指针数组的每一个元素都被填充了一个包含6个数字的数组。

for(int i=0;i<10;i++)
    a[i] = new a[6];

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值