摘要:等我有空再写
第3章 Java 的基本程序设计结构
数据类型
基本数据类型
类型 | 字节数 |
---|---|
int | 4 |
short | 2 |
long | 8 |
byte | 1 |
float | 4 |
double | 8 |
char | 2 |
boolean | 单个boolean变量是4字节 boolean数组的每一个值是1字节 |
整型
在Java中,整型的范围与运行Java代码的机器无关。而C和C++则需要针对不同的处理器选择最为高效的整型。
长整型数值有一个后缀L或l(如9000000000000L)。十六进制数值有一个前缀0x或0X(如0xCAFE)。八进制数值有一个前缀0(如010对应八进制中的8)。
从Java7开始,加上前缀0b或0B就可以写二进制数(如0b1001对应二进制中的9)。同时还可以为数字字面量添加下划线(如0b111_0110_0100_0000_1001_0111),这些下划线只是为了让人们更易读,Java编译器会除去这些下划线。
浮点类型
浮点类型用于表示有小数部分的数值。double类型表示的数值精度是float类型的两倍,绝大部分的程序都使用double类型。
float类型的数值有一个后缀F或f,没有后缀F或f的浮点数值默认为double类型。当然,也可以在浮点数值后添加后缀D或d。
char类型
char类型用于表示单个字符。有些Unicode字符可以用一个char值描述。
boolean类型
boolean(布尔)类型有两个值:false 和 true,用来判定逻辑条件。整型值和布尔值之间不能进行互相转换。
变量
变量名必须是一个以字符开头并由字符或数字构成的序列。其中,字符包括:’A’ ~ ‘Z’、’a’ ~ ‘z’、’_’、’$’或在某种语言中表示字母的任何Unicode字符。
变量初始化
声明一个变量后,必须使用赋值语句对变量进行显式初始化,不要使用未初始化的变量。
常量
在Java中,利用关键字 final 指示常量。关键字 final 表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。
在 Java 中,经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为类常量。可以使用关键字 static final 设置一个类常量。
运算符
在 Java 中,使用算术运算符 +、-、 *、/ 表示加、减、 乘、除运算。 当参与 / 运算的两个操作数都是整数时, 表示整数除法;否则, 表示浮点除法。 整数的求余操作(有时称为取模) 用 % 表示。例如,15/2=7,15%2=1 , 15.0/2=7.50。
需要注意, 整数被 0 除将会产生一个异常, 而浮点数被 0 除将会得到无穷大或 NaN 结果。
数学函数与常量
在Math类中,包含了各种各样的数学函数和数学常量。
数值类型之间的转换
数值类型转换的规则
- 如果两个操作数中有一个是 double 类型,另一个操作数就会转换为 double 类型。
- 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
- 否则,如果其中一个操作数是 long 类型,另一个操作数将会转换为 long 类型。
- 否则,两个操作数都将被转换为 int 类型。
强制类型转换
在上一小节中看到,在必要的时候,int 类型的值将会自动地转换为 double 类型。但另一方面,有时也需要将 double 转换成int。在 Java 中,允许进行这种数值之间的类型转换。当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换(cast)实现这个操作。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。
结合赋值和运算符
可以在赋值中使用二元运算符。如+=、-=、%=、^=等等。
自增与自减运算符
后缀和前缀形式都会使变量值加 1 或减 1。但用在表达式中时,二者就有区别了。前缀形式会先完成加 1;而后缀形式会使用变量原来的值。
1 | int m = 7; |
关系和 boolean 运算符
关系运算符有==、!=、>、<、>=、<=、&&、||等
Java支持三元操作符 ? : ,遵循以下格式
1 | condition ? expressioni : expression |
位运算符
处理整型类型时,可以直接对组成整型数值的各个位完成操作。这意味着可以使用掩码技术得到整数中的各个位。位运算符包括:
1 | &("and") |("or") ^("xor") ~("not") |
括号与运算符级别
1 | a && b || c //从左到右 |
枚举类型
枚举类型包括有限个命名的值。 例如:
1 | enum Size {SMALL, MEDIUM, LARGE} //自定义枚举类型 |
字符串
从概念上讲, Java 字符串就是 Unicode 字符序列。Java 没有内置的字符串类型, 而是在标准 Java 类库中提供了一个预定义类,很自然地叫做 String。
子串
String 类的 substring 方法可以从一个较大的字符串提取出一个子串。
1 | String greeting = "Hello"; |
拼接
与绝大多数的程序设计语言一样,Java语言允许使用 + 号连接(拼接)两个字符串。
1 | String expletive = "Expletive"; |
当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串(在第 5 章中可以看到,任何一个 Java 对象都可以转换成字符串)。
1 | int age = 13; |
如果需要把多个字符串放在一起, 用一个定界符分隔,可以使用静态 join 方法:
1 | String all = String.join(" / ", "S", "M", "L", "XL"); |
不可变字符串
String 类没有提供用于修改字符串的方法6 如果希望将 greeting 的内容修改为“ Help!”,不能直接地将 greeting 的最后两个位置的字符修改为‘ p ’ 和’ ! ‘。如何修改这个字符串呢? 在 Java中实现这项操作非常容易。首先提取需要的字符, 然后再拼接上替换的字符串:
1 | greeting = greeting.substring(0, 3) + "p!"; |
由于不能修改 Java 字符串中的字符, 所以在 Java 文档中将 String 类对象称为不可变字符串, 如同数字3永远是数字3—样,字符串“ Hello” 永远包含字符 H、e、1、1 和 o 的代码单元序列, 而不能修改其中的任何一个字符。当然,可以修改字符串变量 greeting,让它引用另外一个字符串,这就如同可以将存放 3 的数值变量改成存放 4 一样。
不可变字符串却有一个优点:编译器可以让字符串共享。为了弄清具体的工作方式,可以想象将各种字符串存放在公共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串量,原始字符串与复制的字符串共享相同的字符。
如果将 greeting 赋予另外一个值又会怎样呢?
1 | greeting = "Howdy"; |
检测字符串是否相等
可以使用 equals 方法检测两个字符串是否相等。对于表达式:
1 | s.equals(t) |
一定不要使用=运算符检测两个字符串是否相等! 这个运算符只能够确定两个字串是否放置在同一个位置上。(即是否引用的是同一块内存区域)
空船与null串
空串 “” 是长度为 0 的字符串。可以调用以下代码检查一个字符串是否为空:
1 | if (str.lengthQ = 0) |
空串是一个 Java 对象,有自己的串长度(0)和内容(空)。不过,String 变量还可以存放一个特殊的值,名为 null, 这表示目前没有任何对象与该变量关联(关于 null 的更多信息请参见第 4 章)。要检查一个字符串是否为 null, 要使用以下条件:
1 | if (str == null) |
构建字符串
有些时候, 需要由较短的字符串构建字符串, 例如, 按键或来自文件中的单词。采用字符串连接的方式达到此目的效率比较低。每次连接字符串, 都会构建一个新的 String 对象,既耗时, 又浪费空间。使用 StringBuildei•类就可以避免这个问题的发生。
如果需要用许多小段的字符串构建一个字符串, 那么应该按照下列步骤进行。 首先, 构建一个空的字符串构建器:
1 | StringBuilder builder = new StringBuilderO; |
当每次需要添加一部分内容时, 就调用 append 方法。
1 | builder.append(ch); // appends a single character |
在需要构建字符串时就凋用 toString 方法, 将可以得到一个 String 对象, 其中包含了构建器中的字符序列。
1 | String completedString = builder.toStringO; |
StringBuffer和StringBuilder的区别:
- StringBuffer的效率较低,但允许采用多线程的方式执行添加或删除字符的操作
- 如果所有字符串在一个单线程中编辑(通常都是这样),则应该用StringBuilder代替
- 两个类的API是相同的
输入输出
读取输入
要想通过控制台进行输人,首先需要构造一个 Scanner 对象,并与“ 标准输人流” System.in 关联。
1 | Scanner in = new Scanner(System.in); |
现在,就可以使用 Scanner 类的各种方法实现输入操作了。例如, nextLine 方法将输入一行。
1 | String name = in.nextLine(); |
使用 nextLine 方法是因为在输人行中有可能包含空格。要想读取一个单词(以空白符作为分隔符,) 就调用
1 | String firstName = in.next(); |
要想读取一个整数,就调用 nextlnt 方法
1 | int age = in.nextlnt(); |
格式化输出
可以使用 SyStem.0Ut.print(x) 将数值 x 输出到控制台上。这条命令将以 x 对应的数据类型所允许的最大非 0 数字位数打印输出 X。 例如:
1 | double x = 10000.0 / 3.0; |
格式化输出可使用System.out.printf,在printf中,可以使用多个参数
1 | System.out.printf("Hello, %s. Next year, you'll be SSd", name, age); |
文件输入与输出
要想对文件进行读取,就需要一个用 File 对象构造一个 Scanner 对象
1 | Scanner in = new Scanner(Paths.get("niyflle.txt"), "UTF-8"); |
要想写入文件, 就需要构造一个 PrintWriter 对象。
1 | PrintWriter out = new PrintlulriterC'myfile.txt", "UTF-8"); |
要记住一点:如果用一个不存在的文件构造一个 Scanner,或者用一个不能被创建的文件名构造一个 PrintWriter,那么就会发生异常。
控制流程
块作用域
块(即复合语句)是指由一对大括号括起来的若干条简单的 Java 语句。块确定了变量的作用域。一个块可以嵌套在另一个块中。
1 | public static void main(String[] args) { |
条件语句
1 | if (condition) statement |
循环
1 | while (condition) statement |
for 循环
1 | for (statement1; condition; statement2) |
switch语句
switch语句将从与选项值相匹配的 case 标签处开始执行直到遇到 break 语句,或者执行到switch i吾句的结束处为止。如果没有相匹配的 case 标签,而有 default 子句,就执行这个子句。(如果在case分支没有break语句的话,那么会接着执行下一个case分支)。
case标签可以是:
- 类型为 char、byte、 short 或 int 的常量表达式。
- 枚举常量
- 从 Java SE 7开始, case 标签还可以是字符串字面量。
大数值
如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math 包中的两个很有用的类:Biglnteger 和 BigDecimal 这两个类可以处理包含任意长度数字序列的数值。Biglnteger 类实现了任意精度的整数运算,BigDecimal 实现了任意精度的浮点数运算。
使用静态的 valueOf方法可以将普通的数值转换为大数值:
1 | Biglnteger a = Biglnteger.valueOf(100); |
不能使用人们熟悉的算术运算符(如:+ 和 *) 处理大数值。 而需要使用大数值类中的 add 和 multiply 方法。
1 | Biglnteger c = a.add(b); // c = a + b |
数组
数组是一种数据结构, 用来存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。在声明数组变量时, 需要指出数组类型 ( 数据元素类型紧跟 []) 和数组变量的名字。下面声明了整型数组 a:
1 | int[] a; |
不过, 这条语句只声明了变量 a, 并没有将 a 初始化为一个真正的数组。应该使用 new 运算符创建数组。
1 | int[] a = new int[100]; //数组长度不要求是常量:newint[n]会创建一个长度为n的数组。 |
数组初始化以及匿名数组
在 Java中, 提供了一种创建数组对象并同时赋予初始值的简化书写形式。下面是一 例子:
1 | int[] smallPrimes = { 2, 3, 5, 7, 11, 13 }; |
甚至还可以初始化一个匿名的数组:
1 | new int[]{ 17, 19, 23, 29, 31, 37 } |
使用这种语法形式可以在不创建新变量的情况下重新初始化一个数组。
1 | smallPrimes = new int[]{ 17, 19, 23, 29, 31, 37 }; |
数组拷贝
在 Java 中,允许将一个数组变量拷贝给另一个数组变量。这时,两个变量将引用同一个数组:
1 | int[] luckyNumbers = smallPrimes; |
如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf方法:
1 | int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length); |