第一章 Java基本语法
- 1. Java程序剖析
- 1.1 Java代码的基本格式
- 1.2 包、import
- 1.3 类
- 1.4 main()方法
- 1.5 方法
- 1.6 标识符
- 1.7 关键字
- 1.8 修饰符
- 1.9 程序块
- 1.10 语句
- 1.11 Java代码的注释
- 2. 常量与变量
- 2.1 常量
- 2.2 变量
- 2.2 变量的分类
- 2.2.1 成员变量
- 2.2.2 局部变量
- 2.2.3 静态变量
- 2.3 Java中静态变量和成员变量的区别
- 3. 数据类型
- 3.1 整数型
- 3.1.1 byte型
- 3.1.2 short型
- 3.1.3 int型
- 3.1.4 long型
- 3.2 浮点型
- 3.2.1 float型
- 3.2.2 double型
- 3.3 字符型
- 3.4 布尔型
- 3.5 类型转换
- 3.5.1 自动类型转换
- 3.5.2 强制类型转换
- 4. 运算符
- 4.1 赋值运算符
- 4.1.1 基本赋值运算符
- 4.1.2 复合赋值运算符
- 4.2 算术运算符
- 4.3 比较运算符
- 4.4 条件运算符
- 4.5 逻辑运算符
- 4.6 位运算符
- 4.6.1 按位与运算
- 4.6.2 按位或运算
- 4.6.3 按位异或运算
- 4.6.4 按位取反运算
- 4.6.5 左移位运算
- 4.6.6 右移位运算
- 4.6.7 无符号右移运算
- 4.7 自增和自减运算符
- 4.8 运算符优先级
- 5. 流程控制
- 5.1 分支控制
- 5.1.1 if 语句
- 5.1.2 if...else 语句
- 5.1.3 if...else if...else语句
- 5.1.4 嵌套使用 if...else语句
- 5.1.5 switch语句
- 5.2 循环控制
- 5.2.1 for 循环
- 5.2.2 while 循环
- 5.2.3 do while 循环
- 5.2.4 增强型 for 循环
- 5.3 跳转语句
- 5.3.1 break 语句
- 5.3.2 continue 语句
- 5.3.3 return 语句
1. Java程序剖析
1.1 Java代码的基本格式
Java代码的基本格式如下:
package 包名;
import package1.[.package2…].类名;
修饰符 class 类名{
类体;
}
1.2 包、import
Java语言中的一个package(包)就是一个类库单元,包内包含一组类,这一组类在包下被组织起来。在定义包时必须使用关键字package,定义包的语句必须在程序的第一行,当然现在编译器会自动定义包,所以这点了解即可。定义包的语法格式如下:
package 包名;
import的功能是导入包,该语句应位于package语句后:
import package1[.package2…].(类名);
1.3 类
Java是面向对象的程序设计语言,Java程序由类(class)组成,而类是Java程序的基本单元。声明一个类的一般形式如下:
修饰符 class 类名{
类体;
}
1.4 main()方法
main()方法是Java程序执行的入口,其语法格式如下:
public static void main (String[] args) {
方法体;
}
1.5 方法
方法用于改变对象的属性,或者用于接收来自其他对象的信息以及向其他对象发送消息。它在类中用来描述类的行为,其定义格式如下:
修饰符 返回类型 方法名 (参数类型1 参数名1, …, 参数类型n 参数名n) {
//方法体;
return 返回值;
}
1.6 标识符
标识符是用来表示Java中的包、类、方法、变量、常量等的名称。命名规则如下:
① 标识符由字母、数字、下划线及美元符号($)组成
② 标识符首字母不能使用数字
③ 标识符不能是关键字,如class
④ 标识符区分大小写
1.7 关键字
关键字属于特殊的标识符,不能作为一般的标识符来使用,如public、static等,如下:
1.8 修饰符
修饰符指定数据、方法及类的属性的可见度,如public、protected、private等。被它们修饰的数据、方法或类的可见度是不同的
限定词 | 同一类中 | 同一个包中 | 不同包中的子类 | 不同包中的非子类 |
---|---|---|---|---|
private | √ | |||
无限定词 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
Ps:后续再对修饰符作进一步讲解
1.9 程序块
程序块是指一对大括号({})之间的内容,且程序中的大括号必须是成对出现的
1.10 语句
Java程序中语句使用“;”作为语句结尾,而“;”也标志着一个语句的结束
1.11 Java代码的注释
① 单行注释
//注释内容
② 多行注释
/*
注释内容
*/
③ 文档注释
/**
注释内容
*/
2. 常量与变量
2.1 常量
常量就是在程序中固定不变的量,一旦被定义,它的值就不能再被改变
常量声明
在定义常量时需要对常量进行初始化,初始化后,不允许对常量的值进行更改。在Java中,常量名通常使用大写字母,如PI、AGE等。常量声明语法如下:
final 数据类型 常量名称 [= 值]; //[]中的内容为可选
Ps:final修饰成员变量表示常量,值一旦给定就无法改变
常量应用示例
public class constantExample {
static final int AGE = 18;
public static void main(String[] args){
System.out.println("小明今年" + AGE + "岁。");
}
}
运行上述程序,结果如下图所示:
在本案例中,定义了常量AGE,并赋初始值为18,在主函数main()中打印AGE的值
Ps:当常量用于一个类的成员变量时,必须给该常量赋值,否则会出现编译错误
2.2 变量
一些在程序运行过程中数据值会发生改变的数据被称为变量
变量声明
在Java中,所有的变量在使用前必须先声明,声明多个变量时必须使用逗号分隔开,声明变量的基本格式如下:
类型 变量名 [ = value][, 变量名 [= value] …];
声明变量示例
public class variableExample{
public static void main(String[] args){
int a, b, c;
a = b = c = 8;
double pi = 3.14;
String s = "Hello Java";
char x = 'b';
System.out.println("a = " + a + ", b = " + b + ", c = " + c);
System.out.println("pi = " + pi);
System.out.println("s = " + s);
System.out.println("x = " + x);
}
}
上述代码运行结果如下图:
2.2 变量的分类
2.2.1 成员变量
成员变量声明在一个类中,在方法、构造方法及语句块之外,其作用范围为整个类,在这个类中都可以访问到该成员变量。当一个对象被实例化之后,每个成员变量的值也就跟着确定,成员变量在对象创建的时候创建,在对象被销毁的时候销毁,成员变量可以直接通过变量名访问,但在静态方法及其他类中,就要通过类的引用访问。
成员变量的值应该至少被一个方法、构造方法或语句块引用,使得外部能够通过这些方式获取成员变量的信息。
访问修饰符可以修饰成员变量,成员变量对于类中的方法、构造方法或语句块是可见的。一般情况下,应该把成员变量设为私有(private)。通过使用访问修饰符可以使成员变量对子类可见。
成员变量具有默认值,数值型变量的默认值为0,布尔型变量的默认值是false,引用类型变量的默认值是null。
案例演示
public class memberVarExample {
private int year; //定义私有成员变量,仅在该类可见
public void setYear(int year) {
this.year = year; //关于this,在之后的章节会补充
}
//打印成员变量的信息
public void printMember(){
System.out.println("今年是" + year + "年");
}
public static void main(String[] args) {
memberVarExample mve = new memberVarExample(); //创建memberVarExample对象
//通过对象mve调用方法
mve.setYear(2024);
mve.printMember();
}
}
上述代码运行结果如下图所示:
在本案例中,声明了private的成员变量year,它只可以被当前类访问。通过setYear()方法为成员变量year赋值,在main()方法中新建一个memberVarExample对象mve,通过该对象对year赋值并调用printMember()方法打印变量year的信息。
2.2.2 局部变量
局部变量在方法、构造方法或语句块中声明,它在方法、构造方法或语句块被执行的时候创建,当它们执行完成后,变量将会被销毁。访问修饰符不能用于局部变量,局部变量只在声明它的方法、构造方法或语句块中可见。局部变量没有默认值,所以局部变量被声明后,必须经过初始化才可以使用。
案例
public class localVariable {
public void putString(){
String string = "此时相望不相闻,愿逐月华流照君";
System.out.println(string);
}
public static void main(String[] args) {
localVariable variable = new localVariable(); //创建localVariable对象
variable.putString(); //通过对象variable调用putString()方法
}
}
该案例中,定义了putString()方法,在方法中声明了局部变量string并对其进行初始化,然后将其打印出来。在主函数main()中新建localVariable对象并调用putString()方法进行输出。
2.2.3 静态变量
静态变量在类中以static关键字声明,必须在方法、构造方法和语句块外。无论一个类创建多少个对象,类只拥有静态变量的一份拷贝,静态变量的访问格式一般为:
类名.变量名
静态成员变量的默认值和成员变量一样,变量的值可以在声明时指定,也可以在构造方法中指定,除此之外,静态变量还可以在静态语句块中初始化。
案例演示
public class staticVar {
private static String color; //color是静态私有变量
public static final String TOMATO = "番茄";
public static void main(String[] args) {
staticVar.color = "red";
System.out.println(staticVar.TOMATO + "的颜色是" + staticVar.color);
}
}
上述代码运行结果如下图:
Ps:在当前类中访问静态变量可以不加类名直接访问,但是其他类想要访问静态变量,必须使用”类名.静态变量名"的方式,如staticVar.color。
2.3 Java中静态变量和成员变量的区别
类的成员变量按照是否被static修饰可分为两种:一种是被static修饰的变量,叫静态变量,而另一种是没有被static修饰的变量,叫成员变量。
静态变量和成员变量的区别如下:
(1) 静态变量在内存中只有一份拷贝(节省内存),JVM只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配,可以用类名直接访问;
(2) 成员变量是每创建一个对象,就会为成员变量分配一次内存,成员变量可以在内存中有多个拷贝,互不影响(灵活)。
3. 数据类型
Java中数据类型分为基本数据类型和引用类型(reference)。引用类型有类(class)、接口(interface)和数组(array)3种。
Java语言的基本数据类型总共有8种,按用途划分为4个类别:整数型、浮点型、字符型和布尔型。
3.1 整数型
整数型是一类整数值的类型,可以是整数、负数和零。根据所占内存的大小不同,可以分为byte(字节型)、short(短整型)、int(整型)和long(长整型)4种。它们所占内存和取值范围如下表所示:
数据类型 | 占用内存(1字节 = 8位) | 取值范围 |
---|---|---|
byte | 1字节(8位) | -128~127 |
short | 2字节(16位) | -32768~32767 |
int | 4字节(32位) | -2147483648~2147483647 |
long | 8字节(64位) | -9223372036854775808L~9223372036854775807L |
3.1.1 byte型
byte是最小的整数类型,在内存中分配的内存空间最小,只分配1个字节(8位)。byte的取值范围为-128~127,使用时需注意数据溢出产生错误。
3.1.2 short型
short型为短整型,是有符号的16位(2个字节),取值范围为-32768~32767。short型限制数据的存储顺序为先高字节、后低字节,这样在某些机器中就会出错,因此该类型很少被使用。
3.1.3 int型
int型即为整型,是最常用的一种整数类型。int型是有符号的32位(4字节)类型,int型的取值范围是-2147483648~2147483647,足够一般情况下使用,所以是整数类型总应用最广泛的。
3.1.4 long型
long型即为长整型,是有符号的64位(8字节)类型,其取值范围是-263~263- 1。在对long型变量进行赋值时,结尾必须加上L或l,否则将不被认为是long型,建议使用L,因为l容易与数字1混淆。
案例演示
public class Number {
public static void main(String[] args) {
byte b = 112;
short s = 32700;
int i = 600000;
long l = 15000000L;
long add = b + s + i + l;
long subtract = l - i - s - b;
long multiply = i * l;
long divide = l / i;
System.out.println("相加结果:" + add);
System.out.println("相减结果:" + subtract);
System.out.println("相乘结果:" + multiply);
System.out.println("相除结果:" + divide);
}
}
运行结果如下:
3.2 浮点型
浮点型也称为实型,是指带有小数部分的数据。当计算需要小数精度的表达式时,可使用浮点型数据。在Java中浮点型分为单精度浮点型(float)和双精度浮点型(double),它们的取值范围如下表所示:
类型 | 占用内存(1字节 = 8位) | 取值范围 |
---|---|---|
单精度浮点型(float) | 4字节(32位) | -3.4E + 38 ~ 3.4E + 38(6~7位有效小数位) |
双精度浮点型(double) | 8字节(64位) | -1.7E + 308 ~ 1.7E + 308(15位有效小数位) |
3.2.1 float型
float型即单精度浮点型,它表示使用32位(4字节)存储的单精度数值。在给float型变量进行赋值时,在结尾必须加上F或f,如果不加,系统自动将其定义为double型变量
3.2.2 double型
double型即双精度浮点型,它表示64位(8字节)存储的双精度数值。在给double型变量赋值时,可以使用D或d作为后缀来表示该变量为double型数据,也可以不加,对于浮点型数据,系统默认是double型。
3.3 字符型
char型即字符型,使用char关键字进行声明,其占用16位(2字节)的内存空间,用来存储单个字符。char类型的范围是0~65536,没有负值。
类型 | 关键字 | 占用内存 | 取值范围 |
---|---|---|---|
字符型 | char | 16位(2字节) | 0~65536 |
在为char型的变量赋值时,可以使用单引号或数字。char型使用两个字节的Unicode编码表示,Unicode定义了一个完全国际化的字符集,能够表示全部人类语言中的所有字符,为此,Unicode需要16位宽度。因此,在Java中的char是16位的。
在字符类型中有一种特殊的字符,以反斜线“\”开头,后面跟一个或多个字符,该特殊字符叫转义字符。
转义字符 | 含义 |
---|---|
\ddd | 1 ~ 3位八进制字符(ddd) |
\uxxx | 1 ~ 4位十六进制Unicode码字符 |
\’ | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
\n | 换行 |
\f | 换页符 |
\t | 水平跳格符 |
\b | 退格符 |
3.4 布尔型
boolean型即布尔型,使用boolean关键字进行声明,它只有true(真)和false(假)两个值
类型 | 关键字 | 占用内存 | 取值范围 |
---|---|---|---|
布尔型 | boolean | 1字节 | true or false |
Ps:当一个布尔型数据未初始化时,默认值是false而不是true
3.5 类型转换
类型转换即是将一种数据类型转换为另一种数据类型,一般情况下,基本数据类型转换可分为自动类型转换(隐式转换)和强制类型转换(显式转换)两种。
3.5.1 自动类型转换
自动类型转换必须在两种兼容的数据类型之间进行,并且必须是由低精度类型向高精度类型转换。整数类型、浮点型和字符型数据可以进行混合运算。在运算过程中,不同类型的数据会自动转换为同一类型,然后进行运算。
自动转换的规则如下:
(1) 数值型之间的转换:byte ➡ short ➡ int ➡ long ➡ float ➡ double
(2) 字符型转换为整型:char ➡ int
以上类型从左到右依次自动转换,最终转换为同一数据类型。如byte和int类型运算,则转换为int类型,以此类推。
案例演示
public class typeAutoChange {
public static void main(String[] args) {
int i = 15;
float f = 2.5f;
byte b = 2;
char c = 'X';
System.out.println(c - i);
System.out.println(f + i);
System.out.println(b + i + f);
}
}
运行结果如下:
3.5.2 强制类型转换
强制类型转换是将高精度类型向低精度类型进行转换。在进行强制类型转换时,需要注意的是在数据超出低精度数据类型的取值范围时,数据可能不完整,从而导致数据精度降低。强制类型转换格式为:
(目标数据类型) 变量名或表达式;
案例演示
public class forcedChange {
public static void main(String[] args) {
int i = 90;
System.out.println((char)i);
}
}
运行结果如下:
4. 运算符
运算符是在用变量或常量进行运算时经常使用的符号。根据操作数的数目来分,运算符分为一元运算符、二元运算符和三元运算符。根据功能来分,运算符分为赋值运算符、算术运算符、比较运算符、条件运算符、逻辑运算符、位运算符及自增自减运算符。
4.1 赋值运算符
赋值运算符就是用于完成赋值的运算符。最基本的算术运算符就只有一个,就是“=”,而在它的基础之上结合加、减、乘、除等,又形成了复合赋值运算符。
4.1.1 基本赋值运算符
基本赋值运算符“=”是一个二目运算符,其功能是将右边的表达式或者任何数值赋给左边的变量。
4.1.2 复合赋值运算符
在基本的赋值运算符基础上,可以结合算术运算符形成复合运算符,其具有特殊含义。常用的复合赋值运算符如下表所示:
赋值运算符 | 范例 | 含义 |
---|---|---|
+= | a += b | a = a + b |
-= | a -= b | a = a - b |
*= | a *= b | a = a * b |
/= | a /= b | a = a / b |
%= | a %= b | a = a % b |
&= | a &= b | a = a & b |
|= | a |= b | a = a | b |
^= | a ^= b | a = a ^ b |
4.2 算术运算符
算术运算符的功能是进行算术运算。算术运算符可以分为加(+)、减(-)、乘(*)、除(/)及取模这5种运算符,它们组成了程序中最常用的算术运算符。各种算术运算符的含义及其应用如下表所示:
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
+ | 连接的两个变量或常量进行加法运算 | 5 + 6 | 11 |
- | 连接的两个变量或常量进行减法运算 | 5 - 6 | -1 |
* | 连接的两个变量或常量进行乘法运算 | 5 * 6 | 30 |
/ | 连接的两个变量进行除法运算 | 5 / 6 | 0 |
% | 模运算,连接两个变量或常量进行除法运算的余数 | 5 % 6 | 5 |
4.3 比较运算符
比较运算符是指对两个操作数进行关系运算的运算符,属于二元运算符。比较运算符也是Java程序中经常会用到的运算符,它的结果通常是布尔类型,可将它们的比较结果作为判断或循环的条件。常用的比较运算符的含义及应用如下表所示:
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
> | 大于运算符 | 6 > 8 | false |
>= | 大于等于运算符 | 6 >= 8 | false |
< | 小于运算符 | 6 < 8 | true |
<= | 小于等于运算符 | 6 <= 8 | true |
== | 等于运算符 | 6 == 8 | false |
!= | 不等运算符 | 6 != 8 | true |
Ps:注意区分“=”和“==”,前者表示赋值,后者表示比较
4.4 条件运算符
条件运算符的符号是“? : ”,条件运算符属于三目运算符,需要3个操作数,可将其理解为if…else语句的简化,一般语法结构如下:
>Result = <expression> ? <statement1> : <statement2>
案例演示
public class condition {
public static void main(String[] args) {
System.out.println("88和99中最大的值是:" + (88 > 99 ? 88 : 99));
}
}
运行结果如下:
在本案例中,条件是“88 > 99”,若为真,输出88,否则输出99
4.5 逻辑运算符
逻辑运算符用来把各个运算的变量(或常量)连接起来组成一个逻辑表达式,来判断编程中某个表达式是否成立,判断的结果是true或false。逻辑运算符的具体含义及应用如下表所示:
运算符 | 含义 | 实例 | 结果 |
---|---|---|---|
&& | 逻辑与(AND) | false && true | false |
|| | 逻辑或(OR) | false || true | true |
! | 逻辑非(NOT) | !false | true |
逻辑与运算符表示它连接的两个条件同时成立时,整个逻辑与运算才成立;逻辑或运算符表示连接的两个条件其中有一个成立时,整个逻辑或运算就成立;而逻辑非运算符表示相反的运算,如果条件成立则使用逻辑非运算的逻辑表达式值为不成立,反之亦然。
案例
public class logic {
public static void main(String[] args) {
System.out.println("true && false: " + (true && false));
System.out.println("true || false: " + (true || false));
System.out.println("!false: " + !false);
}
}
4.6 位运算符
位运算符主要用于对操作数为二进制的位进行运算。按位运算表示按每个二进制位来进行运算,其操作数的类型是整数类型以及字符类型,位运算符大致分为两大类,即按位运算符和移位运算符,各运算符的含义及功能如下表所示:
4.6.1 按位与运算
按位与运算的运算符为“&”,是双目运算符。其运算规则是:先将参与运算的数转换成二进制数,然后进行低位对齐,高位不足补零;如果对应的二进制位同时为1,则结果为1,否则为0。
案例讲解
2 & 3 = 2
2的二进制数为0010,3的二进制数为0011,按位与的结果是0010,换算成十进制即为2。
4.6.2 按位或运算
按位或的运算符为“|”,是双目运算符,其运算规则也是需要先将参与运算的数转换成二进制,然后进行低位补齐,高位不足补零;如果对应的二进制位有一个为1,结果则为1,否则为0。
案例讲解
5 & 6 = 7
5转为二进制为0101,6的二进制为0110,按位或的结果是0111,换算成十进制即为7。
4.6.3 按位异或运算
按位异或运算的运算符为“^”,是双目运算符,其运算规则是:先将参与运算的数转换成二进制,然后进行低位补齐,高位不足补零,如果对应的位同时为1(或同时为0),结果为0,否则结果为1。
案例讲解
7 ^ 8 = 15
7的二进制数为0111,8的二进制数为1000,按位异或的结果是1111,换算成十进制即为15。
4.6.4 按位取反运算
按位取反运算的运算符为“~”,是单目运算符,其运算规则是:先将参与运算的数转换成二进制数,然后将各位数取反(1改为0,0改为1),二进制数在内存中是以补码形式存在的,最高位为符号位,正数的最高位为0,负数的最高位为1,若按位取反,还需结合最高位考虑
案例讲解
~9 = -10
思路1:首先将9转换成二进制形式,即为0000 1001(这里用八位表示该原码),按位取反(包括符号位)得到1111 0110,除符号位,对其他位进行取反得到1000 1001,然后+1补码得到原码为1000 1010,最高位为1,所以是负数,而1010十进制为10,加上符号便为-10
思路2:将9装换成二进制形式,即为0000 1001, 按位取反得到1111 0110,减1补码得到1111 0101,除符号位取反,得原码1000 1010
思路3:最高位符号位变为1,低位1001加1即可
~-7 = 6
思路1:首先将7转换成二进制形式,即为0000 0111,转化为负数,按位取反(包括符号位)得1111 1000,加1补码得1111 1001,按位取反(包括符号位)得0000 0110,即为6
思路2:首先将7转换成二进制形式,即为0000 0111,将0000 0111减1即为~-7的结果6
总结: 正数按位取反的话,将最高位改为1,低位+1即可;负数按位取反的话,取绝对值的二进制,低位减1即可。记住正+负-就行。
4.6.5 左移位运算
左移位运算的运算符是“<<”,其运算规则是:按二进制形式把所有数字向左移动右边操作数指定的位数,高位数移出(舍弃),低位的空位补零。格式如下:
a << b
该式子表示将a的二进制式的所有数字向左移动b位,相当于a * 2b,如3 << 2,就是将0000 0011向左移动2位,变为0000 1100,结果为3 * 22 = 12。
4.6.6 右移位运算
右移位运算的运算符是“>>”,其运算规则是:按二进制形式把所有数字向右移动右边操作数指定的位数,低位移出(舍弃),高位补符号位(正数补0,负数补1)。格式如下:
c >> d
该式子表示将c的二进制式的所有数字向右移动d位,相当于c / 2d如20 >> 2,就是将 0001 0100向右移动2位,变为0000 0101,结果为 20 / 22 = 5。
4.6.7 无符号右移运算
无符号右移运算的运算符是“>>>”。其运算规则是:按二进制形式把所有数字向右移动右边操作数指定的位数,低位数移出(舍弃),高位补零。同右移位运算相似,只是无符号右移不需要高位补1。
4.7 自增和自减运算符
自增(++)和自减(–)运算符是一种特殊的算术运算符,一般算术运算符需要两个操作数来进行运算,而自增和自减运算符只需要一个操作数。
“++”表示自增运算符,它表示对使用该运算符的变量进行加1的运算:“–”表示自减运算符,它表示对使用该运算符的变量进行减1的运算。当一个自增或自减运算符用在一个变量之前,则表示首先对该变量进行递增或递减运算,然后返回该变量的值。
4.8 运算符优先级
优先级 | 运算符 |
---|---|
1 | 括号,如()和[] |
2 | 一元运算符,如 -、++、-- 和 ! |
3 | 算术运算符,如 *、/、%、+ 和 - |
4 | 关系运算符,如 >、>=、<、<=、==和 != |
5 | 逻辑运算符,如 &、^、|、&&、|| |
6 | 条件运算符和赋值运算符,如 ? : 、=、*=、/=、+= 和 -= |
Ps:在实际编写程序时,应养成使用括号来划分优先级的习惯
5. 流程控制
流程控制语句用于控制程序的流程,以实现程序的各种结构方式。所有应用程序开发环境都提供一个判定过程,称为控制流语句,即程序控制语句,它用于引导应用程序的执行。程序控制语句分为3类:① 分支语句,包括 if 语句和 switch 语句;② 循环语句,包括 for 循环语句、 while循环语句和 do…while循环语句;③ 跳转语句,包括break语句、 continue语句和return语句。
5.1 分支控制
顺序结构只能顺序执行,不能进行判断和选择,因此需要分支结构。分支结构是逻辑选择的核心,同时也是所有流程控制结构中最基础的控制语句。程序在执行过程中会根据条件来选择执行程序分支。分支语句包含两种重要的语句,使用它们可以实现程序流程的分支控制,这两种语句是 if 和 switch 语句。
5.1.1 if 语句
一个 if 语句包含一个布尔表达式和一条或多条语句。if 语句的一般语法结构如下:
if (布尔表达式)
{
//如果布尔表达式为true将执行的语句块
}
如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则执行 if 语句块后面的代码。
案例演示
public class ifTest {
public static void main(String[] args) {
if (1 < 2) {
System.out.println("1恒小于2");
}
}
}
5.1.2 if…else 语句
if语句后面可以跟else语句,当if语句的布尔表达式值为false时,查else语句块会被执行。该语句还可以嵌套使用,完成多路分支及更复杂的程序流程。使用它们的一般语法结构如下:
if (布尔表达式)
{ //如果布尔表达式的值为true
} else {
//如果布尔表达式的值为false
}
案例演示
public class IfElseTest {
public static void main(String[] args) {
if (6 > 8) {
System.out.println("6 > 8");
} else {
System.out.println("8 > 6");
}
}
}
5.1.3 if…else if…else语句
if 语句后面还可以跟else if…else语句,这种语句可以检测到多种可能的情况,它的语法格式如下:
if&ensp(布尔表达式1) {
//如果布尔表达式1的值为true,执行该代码块
} else if (布尔表达式2){
//如果布尔表达式2的值为true,执行该代码块
} else if (布尔表达式3) {
//如果布尔表达式3为true时,执行该代码块
} else{
//当以上布尔表达式的值都为false时,执行该代码块
}
使用 if…else if…else 这个语句时,需要注意以下几点:
(1) if 语句最多只有一个else语句,且else语句要在所有的else…if 语句之后
(2) if 语句可以有若干个else if 语句,它们必须在else语句之前
(3) 一旦其中有一个else if 语句检测为true,其他的else if 及else语句都将跳过执行
案例演示
public class ageTest {
public static void main(String[] args) {
int age = 26;
if (age > 0 && age < 14) {
System.out.println("少年儿童");
} else if(age >= 14 && age < 35) {
System.out.println("青年人");
} else if(age >= 35 && age < 65){
System.out.println("中年人");
} else if (age >= 65){
System.out.println("老年人");
} else{
System.out.println("输入错误!");
}
}
}
5.1.4 嵌套使用 if…else语句
if…else 语句可以实现嵌套使用,不论是在 if 语句块还是在 else 语句块中,都可以再次嵌入 if…else 语句。嵌套使用 if…else 语句,可以实现控制程序的多个流程,实现多路分支,满足编程的需求。嵌套使用 if…else 的语法结构如下:
if (布尔表达式1) {
//如果布尔表达式1值为true,执行代码块
if(布尔表达式2) {
//如果布尔表达式2值为true,执行此代码块
} else {
//如果布尔表达式的值为false,执行此代码块
}
}
案例演示
public class ifTest2{
public static void main (String[] args){
int age = 45;
if (age > 0){
if(age < 14) {
System.out.println("少年");
} else if (age < 35) {
System.out.println("青年人");
} else if (age < 65){
System.out.println("中年人");
} else if (age >= 65) {
System.out.println("老年人");
} else {
System.out.println("输入错误");
}
}
}
}
5.1.5 switch语句
if…else 语句虽然可以嵌套实现程序的多路径分支,但在分支过多的情况下,if…else 嵌套的程序可读性不高,且执行效率低。此时,使用 switch 语句可以解决这个弊端。
switch 语句判断一个变量与一系列值中的某个值是否相等,每个值为一个分支,switch 语句的语法格式如下:
switch (判断的变量) {
case value1:
//执行语句1
break;
case value2:
//执行语句2
break;
…
case value n:
//执行语句n
break;
default: //可选
//执行语句
}
switch语句有如下规则:
(1) switch 语句有多个 case 语句,每个 case 后面跟一个比较比较的值和冒号。
(2) case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。
(3) 当变量的值与 case 语句的值相等时,那么执行这条 case 语句,直到 break 语句出现,跳出 switch 语句。
(4) 遇到 break 语句时,程序跳转到 switch 语句后面执行。如果没有 break 语句出现,成程序会继续执行下一条 case 语句,直到出现 break 语句。
(5) switch 语句还可以包含一个 default 分支,该分支必须是 switch 语句的最后一个分支。 default 语句在没有 case 语句的值和变量值相等的时候执行,default 分支不需要 break 语句。
案例演示
import java.util.Scanner;
public class SwitchWeekTest {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //创建Scanner类对象,我们可以通过Scanner类来获取输入
System.out.print("输入星期几得到这天的英文单词(星期一到星期天):");
String someday = input.next(); //调用Scanner的next()方法获取字符串输入
switch (someday) {
case "星期一":
System.out.println("Monday");
break;
case "星期二":
System.out.println("Tuesday");
break;
case "星期三":
System.out.println("Wednesday");
break;
case "星期四":
System.out.println("Thursday");
break;
case "星期五":
System.out.println("Friday");
break;
case "星期六":
System.out.println("Saturday");
break;
case "星期天":
System.out.println("Sunday");
break;
default:
System.out.println("输入错误!");
}
}
}
5.2 循环控制
顺序结构的程序语句只能被执行一次,如果想要同样的操作执行多次,就需要使用循环结构。 Java中三种主要的循环结构: while循环、 do while循环、 for 循环和增强型 for 循环。
5.2.1 for 循环
for循环语句是技术型循环语句,提前指定循环的次数,适用于循环次数已知的情况。使用for循环时,一般遵循下面的语法结构:
for (初始化; 布尔表达式; 更新)
{
循环体
}
关于 for 循环有以下几点说明:
(1) 首先初始化变量。可以声明一种类型也可初始化一个或多个循环控制变量,还可以是空语句。
(2) 判断布尔表达式的值。如果为true,循环体被执行。如果为false,循环中止,开始执行循环体后面的语句。
(3) 执行一次循环后,更新循环控制变量。
(4) 再次判断布尔表达式,循环执行上面的过程。
案例演示
import java.util.Scanner;
/**
* 输入年月日计算该日是该年的第多少天
*/
public class switchExer {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //Scanner对象创建
System.out.print("请输入年份:");
int year = input.nextInt();
if (year <= 0) System.out.println("年份输入错误!");
System.out.print("请输入月份:");
int month = input.nextInt();
if (month < 1 || month > 12) System.out.println("月份输入错误!");
System.out.print("请输入号数:");
int day = input.nextInt();
int days = 0;
int monthDays = 0;
int newMonth = month;
boolean flag = true; //用来判断输入是否错误
//遍历当前月份之前的所有天数之和
for (--newMonth; newMonth > 0; newMonth--) {
switch (newMonth) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
monthDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
monthDays = 30;
break;
case 2:
if (year % 4 == 0 && year % 100 != 0) { //闰年判定
monthDays = 29;
break;
} else {
monthDays = 28;
break;
}
}
days += monthDays;
}
//判断输入是否出错
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day > 31) {
flag = false;
break;
}
break;
case 4:
case 6:
case 9:
case 11:
if (day > 30) {
flag = false;
break;
}
break;
case 2:
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
if (day > 29) {
flag = false;
break;
}
} else {
if (day > 28) {
flag = false;
break;
}
}
break;
}
//输出
if (flag == true) {
days += day;
System.out.println(year + "年" + month + "月" + day + "日是" +
year + "年第" + days + "天");
} else {
System.out.println("日期输入错误,请检查后重新输入!");
}
input.close(); //释放资源
}
}
此案例中,通过 switch 和 for 循环的简单嵌套来计算某年月日是某年的第多少天
5.2.2 while 循环
while 循环是最基本的循环,它也可以控制一条或者多条语句的循环执行。和 for 循环语句相似,都需要一个判断条件,如果该条件为真则执行循环语句,否则跳出循环。而 for 循环语句与 while 循环语句不同的是 for 循环语句的循环次数确定,而 while 与循环语句的循环次数不确定。While循环的结构如下:
while (布尔表达式)
{
//循环体
}
案例演示
/**
通过while循环计算从1加到100的累加值
*/
public class whileTest {
public static void main(String[] args) {
int i = 1; //循环变量
int sum = 0; //和
while (i <= 100) {
sum += i; //sum = sum + i
i++; //i自增
}
System.out.println(sum);
}
}
5.2.3 do while 循环
while循环有时称为“当型循环”,因为它在循环体执行前先进行条件判断,而do while循环称为“直到型循环”,它会先执行循环体,然后进行条件判断。使用do while循环的一般语法结构如下:
do {
//循环体
} while (布尔表达式);
案例演示
public class DoWhileTest{
public static void main(String[] args) {
int i = 0;
int sum = 0;
do {
sum += i;
i++;
} while (i <= 100);
}
}
5.2.4 增强型 for 循环
增强型 for 循环的语法结构如下:
for (声明语句 : 表达式) {
//代码
}
案例演示
public class StrongForTest {
public static void main(String[] args) {
String[] weeks = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"}; //定义字符串数组,关于数组的内容,之后会补充
for (String week : weeks) {
System.out.println(week);
}
}
}
5.3 跳转语句
在使用循环语句时,只有循环条件表达式的值为假时才能结束循环。如果想提前中断循环,就需要在循环语句块中添加跳转语句。跳转语句有 break 语句、continue 语句和 return 语句。
break 语句跳出循环,执行循环后面的语句。continue 语句是跳过本次循环,开始执行下一次循环。return 语句是跳出方法,并为方法返回相应的值。
5.3.1 break 语句
break主要用于在循环语句或者 switch 语句中,用来跳出整个语句块。break跳出最里层的循环,并且继续执行该循环下面的语句。 break 的使用如前文 switch 中所演示。
5.3.2 continue 语句
continue 适用于任何循环控制结构中,作用是让程序立刻跳转到下一次循环的迭代。在 for 循环中, continue 语句使程序立即跳转到更新语句。在 while 或 do while 循环中程序立即跳转到布尔表达式的判断语句。
案例演示
public class ContinueTest {
public static void main(String[] args) {
int i;
int sum = 0;
//当i为5时,跳出循环
for(i = 0; i <= 10; i ++) {
if (i == 5)
continue;
sum += i;
}
System.out.println(sum);
}
}
上述程序运行结果为50,而1到10的累加值是55,说明,当 i == 5时,程序跳出当次循环,进入到下一次循环中,而5并没有累加。
5.3.3 return 语句
return 语句经常使用在类的方法中,在类中使用 return 语句可以退出类的方法,把控制返回给该方法的调用者;如果方法有返回类型,则必须在方法中使用 return 语句返回一个该类型的值。使用return 语句的一般语法结构如下所示:
return 返回类型;
案例演示
public class ReturnTest {
public static void main(String[] args) {
System.out.println(ReturnTest.test());
}
public static String test() {
return "这是return返回的值";
}
}