2 基本语法
2.1 关键字与保留字
关键字(keyword)
- 定义:被Java语言赋予了特殊含义,用作专门用途的字符串。
- 特点:关键字中所有字母都为小写。
- 官方地址:Java Language Keywords
保留字(reserved word)
- 现有Java尚未使用,但以后版本可能会作为关键字使用。
- 自己命名标识符时要避免使用这些保留字。
- goto、const
2.2 标识符(Identifier)
- 标识符
- Java对各种变量、方法和类等要素命名时使用的字符序列称为标识符。
- 技巧:凡是自己可以起名字的地方都叫标识符。
- 定义合法标识符规则:
- 由26个英文字母大小写,0-9,_或$组成。
- 数字不可以开头。
- 不可以使用关键字和保留字,但能包含关键字和保留字。
- Java中严格区分大小写,长度无限制(其实有限制!!!)。
- 标识符不能包含空格。
Java中的名称命名规范
- Java中的名称命名规范:
- 包名:多单词组成时所有都小写,如xxxyyyzzz
- 类名、接口名:多单词组成时,所有单词的首字母大写,如XxxYyyZzz
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写,如xxxYyyZzz
- 常量名:所有字母都大写。多单词时每个单词用下划线连接,如XXX_YYY_ZZZ
- 注意1:在起名字时,为了提高阅读性,要尽量有意义,“见名知意”。
- 注意2:Java采用Unicode字符集,因此标识符也可以使用汉字声明,但是不建议使用。
2.3 变量
变量的概念
- 内存中的一个存储区域。
- 该区域的数据可以在同一类型范围内不断变化。
- 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值。
变量的作用
- 用于在内存中保存数据。
使用变量注意点
- Java中每个变量必须先声明,后使用。
- 使用变量名来访问这块区域的数据。
- 变量的作用域:其定义所在的一对{}内。
- 变量只有在其作用域内才有效。
- 同一个作用域内,不能定义重名的变量。
变量的使用
- Java定义变量的格式:数据类型 变量名 = 变量值;
public class Test { public static void main(String[] args) { int num; // 1、变量的声明 num = 18; // 2、变量的赋值 System.out.println(num); // 3、变量的使用 int age = 18; // 1、变量的定义 System.out.println(age); // 2、变量的使用 } }
变量的分类
按数据类型
- 对于每一种数据都定义了明确的具体数据类型(强类型语言),在内存中分配了不同大小的内存空间。
按声明位置
- 成员变量:在方法体外,类体内声明的变量。
- 局部变量:在方法体内部声明的变量。
整数类型:byte、short、int、long
Java个整数类型有固定的表示范围和字段长度,不受具体的OS的影响,以保证Java程序的可移植性。
Java的整型常量默认为Int型,声明long型常量需后加“l”或"L“。
Java程序中变量通常声明为int型,除非不足以表示较大的数,才使用long。
bit:计算机中的最小存储单位。byte:计算机中的基本存储单元。
1MB=1024KB,1KB=1024B,1B=1byte=8bit。
public class Test { public static void main(String[] args) { byte b1 = -128; byte b2 = 127; // byte b3 = 128; 编译不通过 short s = 128; int i = 128; long l = 128L; } }
浮点型:float、double
- 与整数类型类似,Java浮点类型也有固定的表示范围和字段长度,不受具体操作系统的影响。
- 浮点型常量有两种表示形式:
- 十进制数形式,如:5.12,512.0f,.512(必须有小数点)
- 科学计数法形式,如:5.1e2,512E2,100E-2
- float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。
- double:双精度,精度是float的两倍。通常采用此类型。
- Java的浮点型常量默认为double型,声明float型常量,须后加“f”或“F”。
字符类型:char
char型数据用来表示通常意义上的“字符”(2字节)。
Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。
字符型变量的三种表现形式:
- 字符常量是用单引号('')括起来的单个字符。例如:
char c1 = 'a'; char c2 = '中'; char c3 = '9';
- Java中还允许使用转义字符''来将其后的字符转变为特殊字符型常量。例如:
char c = '\n';// 表示换行符
- 直接使用Unicode值来表示字符型常量:'\uXXXX\。其中,XXXX表示一个十六进制整数。如:
char c = 97;//表示'a' char a ='\u0041';//表示'A'
- char类型是可以进行运算,因为它有对应的Unicode码。
ASCII码
- 在计算机内部,所有数据都使用二进制表示。每一个二进制位(bit)有0和1两种状态,因此8个二进制位就可以组合出256种状态,这被称为一个字节(byte)。一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000到11111111。
- ASCII码:上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定宁,这被称为ASCII码。ASCII码一共规定了128个字符的编码,比如空格“SPACE"是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。
- 缺点
- 不能表示所有字符。
- 相同的编码表示的字符不一样。
Unicode编码
- 乱码:世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。
- Unicode:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用Unicode没有乱码的问题。
- Unicode的缺点:Unicode只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储(无法区分Unicode和ASCII:计算机无法区分三个字节表示一个符号还是分别表示三个符号)。另外,我们知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节时0,这对于存储空间来说是极大的浪费。
UTF-8
- UTF-8是在互联网上使用最广的一种Unicode的实现方式。
- UTF-8是一种变长的编码方式。它可以使用1-6个字节表示一个符号,根据不同的符号而变化字节长度。
- UTF-8的编码规则:
- 对于单字节的UTF-8编码,该字节的最高位为0,其余7位用来对字符进行编码(等同于ASCII码)。
- 对于多字节的UTF-8编码,如果编码包含n个字节,那么第一个字节的前n位为1,第一个字节的第n+1位为0,该字节的剩余各位用来对字符进行编码。在第一个字节之后的所有的字节,都是最高两位为“01”,其余6位用来对字符进行编码。
布尔型:boolean
- 只有两个值:true、false。
- 常在条件判断、循环结构中使用。
基本数据类型转换
自动类型转换
- 自动类型转换:容量小的类型自动转换为容量大的数据类型。(容量:表示数的范围)
- 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
- boolean类型不能与其他基本数据类型运算。
- 当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。
- 特别地:当byte、char、short三种类型的变量做运算时,结果为int类型。
强制类型转换
- 强制类型转换:强制将容量大的类型转换成容量小的类型。
double d = 12.3; int i = (int)d; // i=12
- 需要使用强转符:()
- 可能导致精度损失。
变量运算规则的特殊情况
long l1 = 123123; // 自动将int --> long √ long l2 = 1111111111111111111111111111111111; // 编译失败:过大的整数 × long l3 = 1111111111111111111111111111111111L; // 编译成功 √ float f1 = 12.3; // 编译失败:double 不能自动转换成 float × float f2 = 12.3F; // 编译成功 √ byte b = 1; byte b2 = b + (byte)1; // 编译失败,byte + byte 运算结果是int × byte b2 = (byte)(b + 1); // 成功 √
字符串类型:String
String不是基本数据类型,属于引用数据类型。
使用方式与基本数据类型一致。例如:
String str = "abc";
- 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。例如:
str = str + "xyz"; int n = 100; str = str + n;
- String可以和8种基本数据类型做运算,且运算只能是连接运算:+。运算的结果是String类型。
进制
所有数字在计算机底层都以二进制形式存在。
对于整数,有四种表示方式:
- 二进制(binary):0,1。以0b或0B开头表示。
- 十进制(decimal):0-9。
- 八进制(ocatal):0-7。以数字0开头表示
- 十六进制(hex):0-9及A-F。以0x或0X开头表示
public class Test { public static void main(String[] args) { int a = 0b110; int b = 110; int c = 0110; int d = 0x110; System.out.println(a);//6 System.out.println(b);//110 System.out.println(c);//72 System.out.println(d);//272 } }
二进制(原码) < — > 十进制
原码、反码、补码
Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位;当是long类型时,二进制默认占64位,第64位是符号位。
二进制的整数有如下三种形式:
- 原码:直接将一个数值转换成二进制数。最高位是符号位。
- 负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。
- 负数的补码:其反码加1。
计算机以二进制补码的形式保存所有的整数。
- 正数的原码、反码、补码都相同。
- 负数的补码是其反码+1。
2.4 运算符
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
- 算术运算符
- 赋值运算符
- 比较运算符(关系运算符)
- 逻辑运算符
- 位运算符
- 三元运算符
2.4.1 算术运算符
正负号(+、-)
加减乘除(+,-,*,/)
取模(%)
自增自减(++,- -)
字符串连接(+)
// 除法/ int a = 12 / 5; // a=2 int b = 12 / 5 * 5; // b=10 double c = 12 / 5; // c=2.0 double d = (double)12 / 5; // d=2.4 // 取模%(结果与被模数符号相同) int e = 12 % 5; // e=2 int f = -12 % 5; // f=-2 int g = 12 % -5; // g=2 int h = -12 % -5; // h=-2 // 自增++(留意局部变量表和操作数栈!!!)(++i:先自增,后运算;i++:先运算,后自增。) int i = 10; i = i++; // i=10 int j = i++; // j=10,i=11 i = ++i; // i=12 j = ++i; // j=13,i=13 short k = 10; //k = k + 1; 编译失败:Type mismatch: cannot convert from int to short k++; // k=11 (short型,效率高)。等价于:k=(short)(k + 1)。【自增不会改变数据类型!!!】 byte l = 127; l++; // l=-128 int i = 0; if (i++ == 0) { System.out.println("if --> " + i); // 结果为true,进入到此语句:if --> 1 } else { System.out.println("else --> " + i); }
public class Test { public static void main(String[] args) { int a = 12 / 5; // a=2 int b = 12 / 5 * 5; // b=10 double c = 12 / 5; // c=2.0 double d = (double)12 / 5; // d=2.4 System.out.println(a); System.out.println(b); System.out.println(c); System.out.println(d); System.out.println("=========="); int e = 12 % 5; // e=2 int f = -12 % 5; // f=-2 int g = 12 % -5; // g=2 int h = -12 % -5; // h=-2 System.out.println(e); System.out.println(f); System.out.println(g); System.out.println(h); System.out.println("==========="); int i = 10; i = i++; // i=10 System.out.println(i); int j = i++; // j=10,i=11 System.out.println("j=" + j + ", i=" + i); i = ++i; // i=12 System.out.println(i); j = ++i; // j=13,i=13 System.out.println("j=" + j + ", i=" + i); System.out.println("============="); short k = 10; //k = k + 1; Type mismatch: cannot convert from int to short k++; // k=11 (short型,效率高)。等价于:s1=(short)(s1 + 1) byte l = 127; l++; // l=-128 System.out.println(l); } }
- 练习
public class Test { /** * 随意给出一个三位数的整数,打印显示它的个位数,十位数,百位数。 */ public static void method(int num) { int a = num / 1 % 10; int b = num / 10 % 10; int c = num / 100 % 10; System.out.println("个位数:" + a); System.out.println("十位数:" + b); System.out.println("百位数:" + c); } public static void main(String[] args) { method(153); method(1534); } }
2.4.2 赋值运算符
符号:=
- 当“=“两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。
- 支持连续赋值。
扩展赋值运算符:+=、-=、*=、/=、%=
// 赋值:= int a = 10; int b = 10; int c = 10, d = 10; // 连续赋值 int e, f; e = f = 10; // += int g = 10; g += 2; // g=12。等价于:g = g +2 short h = 10; //h = h + 2; 编译失败:Type mismatch: cannot convert from int to short h += 2; // h=12(short型),不会改变数据类型
- 练习
// 练习1 short s = 3; // s = s + 2; 编译失败 s += 2; // s=5,short型 // 练习2 int i = 1; i *= 0.1; System.out.println(i) // 0 i++; System.out.println(i); // 1 // 练习3 int m = 2; int n = 3; n *= m++; //n = n * m++ System.out.println("m = " + m); // 3 System.out.println("n = " + n); // 6 // 练习4 int n = 10; n += (n++) + (++n); // n = 10 + 10 + 12 System.out.println(n); // 32
2.4.3 比较运算符
符号
- 等于:==
- 不等于:! =
- 小于:<
- 大于:>
- 小于等于:< =
- 大于等于:> =
- 检查是否是类的对象:instanceof
比较运算符的结果都是boolean型,也就是要么是true,要么是false。
>、<、> =、< =:只能使用在数值类型的数据之间。
==、! =:不仅可以使用在数值类型数据之间,还可以使用在其他引用类型变量之间。
// 1、区分 == 和 = int i = 10; int j = 20; System.out.println(i == j); // false System.out.println(i = j); // 20 boolean b1 = false; boolean b2 = true; System.out.println(b1 == b2); // false System.out.println(b1 = b2); // true
2.4.4 逻辑运算符
符号
- 逻辑与:&
- a & b:a和b都为true时结果为true,否则结果为false
- 逻辑或:|
- a | b:a和b都为false时结果为false,否则结果为true
- 逻辑非:!
- !a:取反
- 逻辑异或:^
- a ^ b:a和b不同时结果为true,否则结果为false
- 短路与:&&
- 短路或:||
- 逻辑与:&
逻辑运算符操作的都是boolean类型的变量。
&、&&
- 相同点
- 运算结果相同
- 当符号左边是true时,二者都会执行符号右边的运算
- 不同点
- 当符号左边是false时,&&不会执行符号右边的运算,直接返回false;&仍然会执行符号右边的运算
- 相同点
|、||
- 相同点
- 运算结果相同
- 当符号左边是false时,二者都会执行符号右边的运算
- 不同点
- 当符号左边是true时,||不会执行符号右边的运算,直接返回true;|仍然会执行符号右边的运算
- 相同点
练习
// 练习1 int x = 1; int y = 1; if (x++ == 2 & ++y == 2) { // (1 == 2 & 2 == 2):false,x=2,y=2 x = 7; } System.out.println("x = " + x + ", y = " + y); //x = 2, y = 2 // 练习2 int x = 1, y = 1; if (x++ == 2 && ++y == 2) { // (1 == 2): false, x=2,y=1 x = 7; } System.out.println("x = " + x + ", y = " + y); // x = 2, y = 1 // 练习3 int x = 1, y = 1; if (x++ == 1 | ++y == 1) { // (1 == 1) | (2 == 1): true, x=2,y=2 x = 7; // x=7 } System.out.println("x = " + x + ", y = " + y); // x = 7, y = 2 // 练习4 int x = 1, y = 1; if (x++ == 1 || ++y == 1) { // (1 == 1): true, x=2,y=1 x = 7; // x=7 } System.out.println("x = " + x + ", y = " + y); // x = 7, y = 1 // 练习5 boolean x = true; boolean y = false; short z = 40; if ((z++ == 40) && (y = true)) { // (true) && (y = true) --> true,z=41 z++; // z=42 } if ((x = false) || (++z == 43)) { // x=false || ((z=43)==43) --> true z++; // z=44 } System.out.println("z = " + z); //z = 44
2.4.5 位运算符
符号
- 左移:<<
- 二进制左移,用0补齐。
- 在不超出范围的情况下,每左移1位,相当于该十进制数乘2。
- 右移:>>
- 二进制右移,正数用0补齐,负数用1补齐。
- 在不超出范围的情况下,每右移1位,相当于该十进制数除以2。
- 无符号右移:>>>
- 二进制右移,用0补齐。
- 与运算:&
- 或运算:|
- 异或运算:^
- 取反运算:~
- 左移:<<
位运算是直接对整数的二进制进行的运算。
练习——交换两个变量的值
int num1 = 10; int num2 = 20; // 方式1:定义临时变量 int temp = num1; num1 = num2; num2 = temp; // 方式2:不用定义临时变量,相加操作可能超出存储范围,非数值型不能使用 num1 = num1 + num2; num2 = num1 - num2; num1 = num1 - num2; // 方式3:使用位运算符(m=m^n^n),不会超出存储范围,只有int类型适合使用 num1 = num1 ^ num2; num2 = num1 ^ num2; num1 = num1 ^ num2;
- 练习——如何求一个0~255范围内的整数的十六进制值,例如60
// 方式1 String str1 = Integer.toBinaryString(60); // "00000000000000000000000000111100" String str2 = Integer.toHexString(60); // "3C" // 方式2 int i1 = 60; int i2 = i1 & 15; String j = (i2 > 9) ? (char)(i2 - 10 + 'A') + "" : i2 + ""; int temp = i1 >>> 4; i2 = temp & 15; String k = (i2 > 9) ? (char)(i2 - 10 + 'A') + "" : i2 + ""; System.out.println(k + "" + j);
2.4.6 三元运算符
格式
- (条件表达式) ? 表达式1: 表达式2
条件表达式为true,执行表达式1;否则执行表达式2。
三元运算符可以嵌套。
凡是可以使用三元运算符的地方,都可以改写为if-else。反之不成立。
// 获取两个数的最大值 int m = 12; int n = 5; int max = (m > n) ? m : n; // 12 String maxStr = (m > n) ? "m" : ((m == n) ? "相等" : "n"); // 获取三个数的最大值 int n1 = 12; int n2 = 30; int n3 = -43; int max1 = (n1 > n2) ? n1 : n2; int max2 = (max1 > n3) ? max1 : n3; System.out.println("三个数中的最大值为:" + max2); int max = (((n1 > n2) ? n1 : n2) > n3) ? ((n1 > n2) ? n1 : n2) : n3;
2.5 程序流程控制
流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。
其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:
- 顺序结构
- 分支结构
- 循环结构
2.5.1 分支结构
1、if-else
// 格式1 if () { } // 格式2 if () { } else { } // 格式3 if () { } else if () { } else { }
- else结构是可选的。
- 多个else if结构时,需要考虑它们之间的顺序。
- if-else结构可以嵌套。
插曲:Scanner的使用
如何从键盘获取不同类型的变量:使用Scanner类。
- 导包:import java.util.Scanner;
- 创建Scanner的对象:Scanner scanner = new Scanner(System.in);
- 调用Scanner对象的相关方法,获取指定类型的变量
- 关闭Scanner对象
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.print("请输入您的姓名:"); String name = scan.next(); System.out.println(name); System.out.print("请输入您的芳龄:"); int age = scan.nextInt(); System.out.println(age); System.out.print("请输入您的体重:"); double weight = scan.nextDouble(); System.out.println(weight); System.out.print("请输入您的性别:"); char gender = scan.next().charAt(0); System.out.println(gender); System.out.print("你是否单身:"); boolean isSingle = scan.nextBoolean(); System.out.println(isSingle); scan.close(); } }
注意:需要根据相应的方法,来输入指定类型的值,如果输入的数据类型与要求的类型不匹配时,会报异常,导致程序终止。
if练习1
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入岳小鹏期末成绩(0~100):"); int score = scan.nextInt(); scan.close(); if (score == 100) { System.out.println("奖励一辆BMW。"); } else if (score > 80 && score <= 90) { System.out.println("奖励一台iphone。"); } else if (score >= 60 && score <= 80) { System.out.println("奖励一个iPad。"); } else { System.out.println("什么也没有。"); } } }
- if练习2
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入第一个整数:"); int num1 = scan.nextInt(); System.out.println("请输入第二个整数:"); int num2 = scan.nextInt(); System.out.println("请输入第三个整数:"); int num3 = scan.nextInt(); scan.close(); if (num1 > num2) { if (num3 > num1) { System.out.println(num3 + " > " + num1 + " > " + num2); } else if (num3 < num2) { System.out.println(num1 + " > " + num2 + " > " + num3); } else { System.out.println(num1 + " > " + num3 + " > " + num2); } } else { if (num3 > num2) { System.out.println(num3 + " > " + num2 + " > " + num1); } else if (num3 < num1) { System.out.println(num2 + " > " + num1 + " > " + num3); } else { System.out.println(num2 + " > " + num3 + " > " + num3); } } } }
- 面试题
// 面试题1,if-else省略花括号罩住一行,输出:(2) int x = 4; int y = 1; if (x > 2) { if (y > 2) System.out.println("(1)"); System.out.println("(2)"); } else System.out.println("(3)"); // 面试题2,省略花括号,else就近原则,输出:(3) int x = 4; int y = 1; if (x > 2) if (y > 2) System.out.println("(1)"); // System.out.println("(2)"); else System.out.println("(3)");
插曲:如何获取一个随机数——Math.random()
double res = Math.random(); // res是double类型,取值范围:[0.0, 1.0) // 如何获取10~99的随机数 int res = (int)((Math.random() * 90) + 10); // 公式:[a, b] ——> (int)(Math.random() * (b - a + 1) + a)
2、switch-case
switch (表达式) { case 常量1: 执行语句; break; case 常量2: 执行语句; break; …… default: 执行语句 }
根据switch表达式中的值,依次匹配各个case中的常量。一旦匹配成功,则进入相应case结构,调用其执行语句。当调用完执行语句以后,仍然继续向下执行其他case结构中的执行语句,直到遇到break关键字或此switch-case末尾结束为止。
break关键字,可以使用在switch-case结构中,表示一旦执行到此关键字,就跳出switch-case结构。
switch结构中的表达式,只能是如下的6种数据类型之一(Only convertible int values, strings or enum variables are permitted):
- byte
- short
- char
- int
- enum(JDK5.0新增)
- String(JDK7.0新增)
case后只能声明常量,不能声明范围。
break关键字是可选的。
default相当于if-else结构中的else。default结构是可选的,而且位置是灵活的。
凡是可以使用switch-case的结构,都可以转换为if-else;反之不成立。
我们写分支结构时,当发现既可以使用switch-case(case情况不能太多),又可以使用if-else时,优先使用switch-case。
实例
public class Test { public static void main(String[] args) { int number = 2; switch(number) { case -1+1: System.out.println("zero"); break; case (0+1): System.out.println("one"); break; case 2: System.out.println("two"); break; case 3: System.out.println("three"); break; default: System.out.println("other"); } } }
public class Test { public static void main(String[] args) { int score = 78; switch(score / 10) { case 0: case 1: case 2: case 3: case 4: case 5: System.out.println("不及格!"); break; case 6: case 7: case 8: case 9: case 10: System.out.println("及格!"); } switch(score/60) { case 0: System.out.println("不及格!"); break; case 1: System.out.println("及格!"); } } }
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入2019年的month:"); int month = scan.nextInt(); System.out.println("请输入2019年的day:"); int day = scan.nextInt(); scan.close(); int sumDays = 0; switch(month) { case 12: sumDays += 31; case 11: sumDays += 30; case 10: sumDays += 31; case 9: sumDays += 30; case 8: sumDays += 31; case 7: sumDays += 31; case 6: sumDays += 30; case 5: sumDays += 31; case 4: sumDays += 30; case 3: sumDays += 31; case 2: sumDays += 28; case 1: sumDays += day; } System.out.println("2019年" + month + "月" + day + "日是2019年的第" + sumDays + "天"); } }
import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入年份:"); int year = scan.nextInt(); System.out.println("请输入" + year + "年的month:"); int month = scan.nextInt(); System.out.println("请输入" + year + "年的day:"); int day = scan.nextInt(); scan.close(); int sumDays = 0; switch(month) { case 12: sumDays += 31; case 11: sumDays += 30; case 10: sumDays += 31; case 9: sumDays += 30; case 8: sumDays += 31; case 7: sumDays += 31; case 6: sumDays += 30; case 5: sumDays += 31; case 4: sumDays += 30; case 3: sumDays += 31; case 2: if ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) { sumDays += 29; } else { sumDays += 28; } case 1: sumDays += day; } System.out.println(year + "年" + month + "月" + day + "日是2019年的第" + sumDays + "天"); } }
2.5.2 循环结构
- 在某些条件满足的情况下,反复执行特定代码的功能。
- 循环语句分类
- for
- while
- do-while
- 循环语句的四个组成部分
- ①初始化条件
- ②循环条件 ——> boolean类型
- ③循环体
- ④迭代部分
1、for
for (①; ②; ④) { ③ }
执行过程:① —>【② —> ③ —> ④ —> ② —> ③ —> ④】—> ② —>
练习
int num = 1; for (System.out.print('a'); num <= 3; System.out.print('c'),num++) { System.out.print('b'); } // 输出结果:abcbcbc // 遍历100以内的偶数 for (i = 1; i <= 100; i++) { if (i % 2 == 0) { System.out.print(i + " "); } } // i在for循环内有效,出了for循环就失效了 // 遍历100以内的偶数,输出所有偶数的和 int sum = 0; for (int i = 1; i <= 100; i++) { if (i % 2 == 0) { sum += i; } } System.out.println(sum); // 遍历100以内的偶数,输出所有偶数的个数 int count = 0; for (int i = 1; i <= 100; i++) { if (i % 2 == 0) { count++; } } System.out.println(count);
- 例题
/* 编写程序从1循环到150,并在每行打印一个值,另外在每个3的倍数行上打印出“foo”, 在每个5的倍数行上打印出“biz”,在每个7的倍数行上打印出”baz“。 */ for (int i = 1; i <= 150; i++) { System.out.print(i); if(i % 3 == 0) { System.out.print(" foo"); } if(i % 5 == 0) { System.out.print(" biz"); } if(i % 7 == 0) { System.out.print(" baz"); } System.out.println(); }
/* 输入两个正整数m和n,求其最大公约数和最小公倍数。 比如:12和20的最大公约数是4,最小公倍数是60。 说明:break关键字的使用。 */ import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("请输入第一个正整数:"); int m = scan.nextInt(); System.out.println("请输入第二个正整数:"); int n = scan.nextInt(); scan.close(); for (int i = (m > n) ? n : m; i >0; i--) { if (m % i == 0 && n % i == 0) { System.out.println("最大公约数是:" + i); break; } } for (int i = (m > n) ? m : n; i <= m*n; i++) { if (i % m == 0 && i % n == 0) { System.out.println("最小公倍数是:" + i); break; } } } }
2、while
① while(②) { ③ ④ }
执行过程:① —>【② —> ③ —> ④ —> ② —> ③ —> ④】—> ② —>
注意:while循环千万不要丢了④,一旦丢了,就可能导致死循环。
for循环和while循环可以相互转换。
例题
// 遍历100以内的所有偶数 int i = 1; while (i <= 100) { if (i%2 == 0) { System.out.println(i); } i++; }
3、do-while
① do { ③ ④ } while(②);
执行过程:① —>【③ —> ④ —> ② —> ③ —> ④】—> ② —>
do-while循环至少会执行一次循环体。
// 遍历100以内的偶数 int num = 1; do { if (num % 2 == 0) { System.out.println(num); } num++; } while(num <= 100);
循环结构综合例题
不在循环条件部分限制次数的结构:for(;;)或while(true)
结束循环有几种方式?
- 方式一:循环条件部分返回false
- 方式二:在循环体中,执行break
/* 从键盘读入个数不确定的整数,并判断读入的整数和负数的个数,输入为0时结束程序。 */ import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int posCounts = 0; int negCounts = 0; int num = 0; while(true) { System.out.println("请输入一个整数:"); num = scan.nextInt(); if (num == 0) { scan.close(); break; } else if (num > 0) { posCounts++; } else { negCounts++; } } System.out.println("正数的个数为:" + posCounts); System.out.println("负数的个数为:" + negCounts); } }
/* 从键盘读入个数不确定的整数,并判断读入的整数和负数的个数,输入为0时结束程序。 */ import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int posCounts = 0; int negCounts = 0; int num = 0; for(;;) { System.out.println("请输入一个整数:"); num = scan.nextInt(); if (num == 0) { scan.close(); break; } else if (num > 0) { posCounts++; } else { negCounts++; } } System.out.println("正数的个数为:" + posCounts); System.out.println("负数的个数为:" + negCounts); } }
嵌套循环
嵌套循环:将一个循环结构A,声明另一个循环结构B的循环体中,就构成了嵌套循环。
外层循环:B;内层循环:A
内层循环结构遍历一遍,只相当于外层循环体执行了一次。
假设外层循环需要执行m次,内存循环需要执行n此。此时内存循环的循环体一共执行了m*n次。
for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 6; j++) { System.out.print("*"); } System.out.println(); }
// 九九乘法表 for (int i = 1; i <= 9; i++) { for(int j = 1; j <= i; j++) { System.out.print(i + " * " + j + " = " + (i * j) + "\t"); } System.out.println(); }
// 100以内的所有质数的输出。 boolean flag = true; for(int i = 2; i <= 100; i++) { for (int j = 2; j < i; j++) { if(i % j == 0) { flag = false; break; } } if(flag) { System.out.println(i); } flag = true; }
2.5.3 break、continue
break
- switch-case结构、循环结构
- 结束当前循环
continue
- 循环结构
- 结束当次循环
for(int i = 1; i <= 100; i++) { if(i % 4 == 0) { break; // continue; } System.out.println(i); }
- 标签
// 不带标签 for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 10; j++) { if(j % 4 == 0) { break; // 默认跳出包裹此关键字的最近的一层循环 // continue; } System.out.println(j); } System.out.println(i); } // 带标签 label: for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 10; j++) { if(j % 4 == 0) { break label; // 跳出命名为label的那层循环 // continue label; } System.out.println(j); } System.out.println(i); }
2.5.4 return
- return:并非专门用于结束循环,它的功能是结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束。
- 与break和continue不同的是,return直接结合整个方法,不管这个return处于多少层循环之内。