第二章 Java 基础语法
关键字和保留字
关键字
定义: 被Java语言赋予了特殊含义,用做专门用途的字符串(单词)
特点: 关键字中所有字母都为小写
用于定义数据类型的关键字
- class、interface、enum、byte
- short、int、long、float、double
- char、boolean、void
用于定义流程控制的关键字
- if、else、swtich、case、default
- while、do、for、break、continue、return
用于定义访问权限修饰符的关键字
- private、protected、public
保留字
现有Java版本尚未使用,后续版本可能会作为关键字使用
- goto
- const
标识符
Java 对各种变量、方法和类等要素命名时使用的字符序列称为标识符
技巧: 凡是自己可以起名字的地方都叫标识符
定义合法标识符的规则:
- 由26个英文字母大小写,0-9,_或$组成
- 不能以数字开头
- 不能使用关键字和保留字,但可以包含它们
- 严格区分大小写,长度无限制
- 不能包含空格
Java 中的标识符命名规范
见名知意,Java 采用unicode字符集,因此标识符可以使用汉字声明,但不建议使用
- 包名: 多个单词组成时所有字母小写: xxxyyyzzz
- 类名、接口名: 多个单词组成时,所有单词的首字母大写: XxxYyyyZzz
- 变量名、方法名: 多单词组成时,除去第一个单词外,其余单词首字母大写: xxxYyyZzz
- 常量名: 所有字母都大写,多单词时,每个单词用下划线连接: XXX_YYY_ZZZ
变量(重点)
- 内存中的一个存储区域
- 该去域的数据可以在同一类型范围内不断变化
- 变量是程序中最基本的存储单元;包含 变量类型、变量名和存储的值
变量的作用
- 用于在内存中保存数据
变量使用中的注意事项
- Java 中每个变量必须先声明后定义
- 使用变量名来访问这块区域的数据
- 变量的作用域: 其所在的一对 "{...}"内
- 变量只有在其作用与内才有效
- 同一个作用域内不能定义重名的变量
变量的使用
-
Java定义变量的格式: 数据类型 变量名 = 变量值
-
说明
- 变量必须先声明后使用
- 变量都定义在其作用域内,在作用域内,它是有效的,反之无效
- 同一个作用域内,不能声明两个同名的变量(逆向思维,反证法)
基本数据类型(8种)
数值型
-
整数类型
- Java各整数类型有固定的表述范围和字段长度,不受具体OS的影响,以保证java程序的可移植性
- java的整型常量默认为int型,声明long型常量后需加"l"/"L"
- java程序中,变量通常声明为
int型,除非不足以表示较大的数,才使用long型
- byte 1字节=8bit -128 ~ 127 === 2^8
byte b1 = 12; byte b2 = -128; // byte b3 = 128; error 编译不通过- short 2字节 -2^15 ~ 2^15 - 1 === 2^16
short s1 = 123- int 4字节 -2^31 ~ 2^31 - 1 (约21亿) === 2^32
int i1 = 1234- long 8字节 -2^63 ~ 2^63 - 1 === 2^64
// 声明long类型变量,必须以"l"/"L"结尾 long l1 = 852096374L -
浮点型
- 浮点型,表示带小数点的数值
- float表示数值的范围比long还要大
- 定义float类型变量时,变量要以"f"/"F"结尾
- Java的浮点型常量默认为
double型
- float: 单精度,尾数可以精确到7位有效数字,多数情况下很难满足需求
// E === 10 // 4字节,表数范围 -3.403E38 ~ 3.403E38 float f1 = 12.3F; // float f2 = 123.4; // error- double: 双精度,精度是float的两倍;通常采用此类型
// 8字节,-1.798E308 ~ 1.798E308 double d1 = 85.0;
字符型 char (1字符=2字节)
-
定义char型变量,通常使用一对单引号(''),也可以写ASCII码,不能使用双引号("")
-
单引号中只能写一个字符,字符串中可以写多个字符
-
表示方式:
- 声明一个字符
- 转义字符
- Unicode 值表示(很少)
-
转义字符:
- \b: 退格符
- \n: 换行符
- \r: 回车符
- \t: 制表符
- \": 双引号
- \': 单引号
- \\: 反斜线
char c1 = 'a';
char c11 = 97; // 'a'
c1 = 'A';
// c1 = 'ab'; // error
char c2 = '中';
// 转义字符
char c3 = '\n'; // 换行符
System.out.print("hello" + c3);
System.out.println("world");
// hello
// world
char c4 = '\t'; // 制表符 tab 键
System.out.print("hello" + c4);
System.out.print("world");
// hello world
// Unicode值
char c5 = '\u0043';
System.out.print(c5)
// c
布尔型 boolean
- 只能取两个值之一: true / false
- 常用于条件判断、循环结构中使用
boolean bb1 = true;
System.out.println(bb1);
// true
boolean isMarried = true;
if (isMarried) {
System.out.println("sorry,\n你不能参加\"单身\"派对!");
// sorry,
// 你不能参加"单身"派对!
}else {
System.out.println("请来参加单身派对!");
}
基本数据类型间的转换
前提: 这里只讨论7种基本数据类型间的运算,不包含boolean类型
自动类型转换(提升)
- 同种数据类型中: 小类型 和 大类型 作运算时,结果自动提升为 大类型
- byte、char、short -> int -> long -> float -> double
- 特殊: 当 byte、short、char 三者之间作运算时,结果为int型
byte b1 = 2;
int i1 = 129;
// byte b2 = i1 + b1; error 编译不通过
int i2 = i1 + b1;
long l1 = i1 + b1;
float f1 = i1 + b1;
System.out.println(i2); // 131
System.out.println(f1); // 131.0
- char类型与数据类型作运算,最小结果类型为int类型
char c1 = 'a' // 97
int i3 = 10;
int i4 = c1 + i3;
System.out.println(i4); // 107
short s1 = 10;
// char c2 = c1 + s1; // error 编译不通过
byte b1 = 10;
short s2 = b1 + s1; // error 编译不通过
byte b2 = 10;
byte b3 = b1 + b2; // error 编译不通过
int i5 = b1 + b2; // 只能通过int型来接收
System.out.println(i5); // 20
强制类型转换
强制类型转换: 自动类型提升的逆运算(大类型转为小类型)
- 强转符: "(数据类型)", 数据类型 变量 = (数据类型)变量;
- 注意,强制类型转换,可能导致精度损失
double d1 = 12.8;
int i1 = (int)d1; // 截断操作,损失精度
System.out.println(i1); // 12
long l1 = 123L;
short s1 = (short)l1; // 截断操作,没有精度损失
实际编码中的数据转换
- long: 定义变量时,数据值没有超过int型时可以不加"l"/"L"
long l1 = 12345; // 默认 12345 为int型,可以转为long型
System.out.print(l1) // 12345
long l2 = 123456789134568; // error, 数据值超过int范围
- float: 定义变量时一定要加"f"/"F"
float f1 = 12.3; // error,默认 12.3 为double型,不能转化为 float型
float f2 = 1 + 12.3; // 12.3默认为double型
- byte: Java中的整型数据默认为int型
byte b1 = 12;
byte b2 = b1 + 1; // error, 整数 1 默认为int型,故b2的数据类型应该为 int型
int b2 = b1 + 1;
- 总结: 整型常量,默认为int型;浮点型常量,默认为double型
基本数据类型与String(class)间转换
String: 字符串类型
-
String不是基本数据类型,属于引用数据类型
-
声明String类型的变量时,必须使用一对双引号:
"" -
使用方式与基本数据类型一致;如 String s1 = "ads";
-
一个字符串可以串接另一个字符串,也可以直接串接其它类型的数据
String s1 = "ads"; s1 = s1 + '123'; int n = 100; s1 = s1 + n String s2 = "1"; String s3 = ""; -
String可以和8中基本数据类型变量作运算,且运算只能是连接运算: "+"(连接符)
-
String类型与其它类型的运算结果仍然是String类型
int number = 1001; String numberStr = "学号: "; String info = numberStr + numner; System.out.print(info); // 学号: 1001 boolean b1 = true; String info1 = info + b1; System.out.print(info1); // 学号: 1001true
练习
// 1.
char c = 'a';
int num = 10;
String str = 'hello';
System.out.print(c + num + str); // 107hello
System.out.print(c + str + num); // ahello10
System.out.print(c + (num + str)); // a10hello
System.out.print((c + num) + str); // 107hello
System.out.print(str + num + c); // hello10a
// 2.
System.out.println("* *"); // * *
System.out.println('*' + '\t' + '*'); // 93
System.out.println('*' + "\t" + '*'); // * *
System.out.println('*' + '\t' + "*"); // 51*
System.out.println('*' + ('\t' + "*")); // * *
// 3.
String str1 = 4; // error
String str1 = 3 + ""; // success
String str2 = 3.5F + ""; // "3.5"
System.out.println(3 + 4 + "Hello!"); // 7Hello!
System.out.println("Hello!" + 3 + 4); // Hello!34
System.out.println('a' + 1 + "Hello!"); // 98Hello!
System.out.println("Hello!" + 'a' + 1); // Hello!a1
// 4. 变量提升
short s1 = 5;
s1 = s1 + 2; // error
int s2 = s1 + 2; // success
byte b = 3;
b = b + 4; // error
b = (byte)(b + 4); // success
char c1 = 'a';
int i1 = 5;
float d = 3.14F;
double result = c1 + i1 + d; // success
byte b = 5;
short s = 3;
short t = s + b; // error
int t = s + b; // success
进制与进制间的转换(了解)
关于进制
-
所有数字在计算机底层都以二进制形式存在
-
对于整数,有四种表示方式
- 二进制(binary): 0-1; 满二进一,以0b或0B开头
- 十进制(decimal): 0-9; 满十进一
- 八进制(octal): 0-7; 满八进一,以数字0开头表示
- 十六进制(hex): 0-9及A-F; 满十六进一,以0x或0X开头表示(此处A-F不区分大小写)
int num1 = 0B110; // 6
int num2 = 100; // 100
int num3 = 0127; // 87
int num4 = 0X110A; // 4362
进制转换
每个进制的最高位称为
符号位,0:正数,1:负数
正数中二进制到十进制的转换
int i = 0B1110;
// 0*2^0 + 1*2^1 + 1*2^2 + 1*2^3 = 14
十进制转化为二进制: 商除二,取余的逆
二进制转八进制: 从低向高,每三个二进制位代表一个八进制位
二进制转十六进制: 从低向高,每四个二进制位代表一个十六进制位
二进制
-
二进制的整数有如下三种形式:
- 原码: 直接将一个数值转换为二进制
- 负数的反码: 对原码按位取反,只是最高位(符号位)确定为1
- 负数的补码: 其反码加1
-
计算机以二进制
补码的形式保存所有的整数- 正数的原码、反码、补码都相同
- 负数的补码是其反码加1
负数中二进制到十进制的转换
1 0 0 0 1 1 1 0 // -14的原码
// 除去符号位外,各个位取反
1 1 1 1 0 0 0 1 // -14的反码
// 反码 +1
1 1 1 1 0 0 1 0 // -14的补码
// 计算机底层都以补码的形式来存储数据!
// 练习
1 0 1 1 1 0 1 1 // 补码
// 补码 -1
1 0 1 1 1 0 1 0 // 反码
// 除符号位,反码取反
1 1 0 0 0 1 0 1 // 原码
1*2^0 + 1*2^2 + 1*2^6 = -69
//
0 1 1 1 1 1 1 1 // +127
1 1 1 1 1 1 1 1 // -127原码
1 0 0 0 0 0 0 1 // -127补码
1 0 0 0 0 0 0 0 // -128补码
总结(重点)
标识符的命名规则
- 以字母a-Z(区分大小写)、0-9、_和$表示
- 不能以数字开头
- 不能包含空格
- 不能使用关键字保留字,但是可以包含关键字保留字
标识符的命名规范(见名知意)
- 包: xxxyyyzzz
- 类名、接口名: XxxYyyZzz
- 变量名、方法名: xxxYyyZzz
- 常量: XXX_YYY_ZZZ
Java 变量的数据类型的划分,并指出Java的8中基本数据类型,及各自所占空间大小
- Java 变量的数据类型分为
-
基本数据类型
-
数值型
- 整数类型 byte、short、int、long
- 浮点类型 float、bouble
-
字符型 char
-
布尔型 boolean
-
-
引用数据类型
- 类
- 接口
- 数组
- Java 中的8中基本数据类型
- byte: 1字节=8位 2^8, -128 ~ 127
- short: 2字节=16位 2^16, -2^15 ~ 2^15
- int: 4字节=32位 2^32, -2^31 ~ 2^31
- long: 8字节=64位 2^64, -2^63 ~ 2^63
- float: 4字节
- double: 8字节
- char: 1字符=2字节
- boolean:true/false
基本类型间自动类型提升的运算规则
- byte、short、char -> int -> long -> float -> double
- String与8种基本数据类型变量作连接运算"+"都为String类型
基本数据类型之间强制类型转换的使用规则和可能出现的问题
- 容量大 -> 容量小
- 变量类型 变量名 = (变量类型)变量值;
- 可能出现精度丢失
进制
二进制数据的存储方式: 所有数值,不管正负,底层都是以补码的方式存储
- 正数: 原码、反码、补码 三码合一
- 负数: 补码 = 反码 +1
运算符
算数运算符
-
+ 正号/加/字符串连接
-
- 负号/减
-
* 乘
-
/ 除
int num1 = 12; int num2 = 5; int result1 = num1 / num2; // 2 int result2 = num1 / num2 * num2; // 10 double result3 = num1 / num2; // 2.0 double result4 = num1 / (num2 + 0.0); // 2.4 double result5 = (double)num1 / num2; // 2.4 -
% 取余,余数的符号与被除数的符号相同
int m1 = 12; int n1 = 5; int res1 = m1 % n1; // 2 // 余数的符号与被除数的符号相同 int m2 = -12; int n2 = 5; int res2 = m2 % n2; // -2 int m3 = 12; int n3 = -5; int res3 = m3 % n3; // 2 int m4 = -12; int n4 = -5; int res4 = m4 % n4; // -2 -
++ 自增1
- 前自增: 先自增一,后运算
int a1 = 10; int b1 = ++a1; System.out.print("a1= " + a1 + ", b1= " + b1); // a1 = 11, b1 = 11- 后自增: 先运算,后自增一
int a2 = 10; int b2 = a2++; System.out.print("a2= " + a2 + ", b2= " + b2); // a2 = 11, b2 = 10 short a3 = 10; // a3 = a3 + 1; error 编译失败 // a3 = (short)(a3 + 1); // success a3++; // 自增1,不会改变本身变量的数据类型,效率更高 // 问题 byte bb1 = 127; bb1++; System.out.pringln("bb1 = " + bb1); // bb1 = -128 // 1 0 0 0 0 0 0 0 -
-- 自减1,与自增1类似
int a4 = 10; int b4 = a4--; System.out.println("a4 = " + a4 + ", b4 = " + b4); // a4 = 9, b4 = 10 // 去除一个三位数的个、十、百位的值 int num = 187; int bai = num / 100; int shi = num % 100 / 10; // num / 10 % 10; int ge = num % 10;
赋值运算符: =
- 当"="两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理
支持连续赋值- 扩展运算符: +=、-=、*=、/=、%=
- 运算的结果不会改变变量本身的数据类型
int i1 = 10;
int j1 = 10;
int i2, j2;
i2 = j2 = 10; // 连续赋值
int i3 = 10, j3 = 20;
int num1 = 10;
num1 += 2; // num1 = num1 + 2;
System.out.println(num1); // 12
int num2 = 12;
num2 % = 5;
System.out.println(num2); // 2
short s1 = 10;
s1 += 2; // 不会改变变量本身的数据类型,效率更高
System.out.println(s1); // 12
// 开发中,如果希望变量实现加2的操作,有几种方法?
int num = 2;
num = num + 2; // 1.
num += 2; // 2.效率更高
// 练习1
int i = 1;
i *= 0.1;
System.out.println(i); // 0
i++;
System.out.println(i); // 1
// 练习2
int m = 2;
int n = 3;
n *= m++;
System.out.println("m = " + m); // 3
System.out.println("n = " + n); // 6
// 练习3
int n = 10;
n += (n++) + (++n);
System.out.println(n); // 32
比较运算符
比较运算符的结果都是 boolean 类型
- == 相等于 4==3 false
- != 不等于 4!=3 true
- < 小于 4<3 false
- /> 大于 4>3 true
- <= 小于等于 4<=3 false
- >= 大于等于 4>=3 true
- instanceof 检查是否是类的对象 "Hello!" instanceof String true
逻辑运算符
操作的都是布尔类型的变量
- & 逻辑与
- | 逻辑或
- ! 逻辑非
- && 短路与
- || 短路或
- ^ 逻辑异或 a^b 相同为false,异同为true
& 与 && 的异同(开发中推荐使用 && )
-
相同点:
- & 与 && 的运算结果相同
- 当符号左边为 true时,两者都会执行符号右边的运算
-
异同点:
- 当符号左边是false时,& 继续执行符号右边的运算,&& 不再执行符号右边的运算
int x = 1;
int y = 1;
if(x++==2 & ++y==2) {
x = 7
}
System.out.println("x= " + x + ", y= " + y);
// x=2, y=2
int i = 1, j = 1;
if(i++==2 && ++j==2) { i = 7 }
System.out.println("i= " + i + ", j= " + j);
// i = 2, j = 1
| 与 || 的异同(开发中推荐使用 || ),与上边类似
位运算符(了解)
位运算是直接对整数的二进制进行的运算
- << 左移(*2^n) 3<<2=12 -> 3*2*2=12
- 左移,在一定范围内 res*2^n, n是左移的位数
- 规则: 空位补0,被移除的高位直接丢弃
- >> 右移(/2^n) 3>>1=1 -> 3/2=1
- 右移,在一定范围内 res/2^n, n是右移的位数
- 规则: 正数,右移后空缺位补0;负数,右移后空缺位补1
- >>> 无符号右移(集合,求hash值) 3>>>1=1 -> 3/2=1
- 规则: 右移,空缺位直接补0
- & 与运算 6&3=2
- | 或运算 6|3=7
- ^ 异或运算 6^3=5
- ~ 取反运算 ~6=-7
// 面试题: 最高效方式计算 2*8
2 << 3; // 2*2*2*2
8 << 1; // 8*2
// 练习: 交换两个变量的值
int i = 12;
int j = 22;
// 1. 通用性
int temp = i;
i = j;
j = temp;
// 2. 可能超出存储范围,只能操作数值型
num1 = num1 + num2;
num2 = num1 - num2;
num1 = num1 - num2
// 3. k = m ^ n; m = k ^ n = (m ^ n) ^ n (规则)
// 有局限性,只适用于数值类型
i = i ^ j;
j = i ^ j;
i = i ^ j;
三元运算符
格式: 数据类型 变量名 = (条件表达式) ? 表达式1 : 表达式2;
- 条件表达式为 true,执行表达式1, 反之,执行表达式2
- 表达式1和表达式2为同种类型
- 三元运算符可以嵌套使用
- 三元运算符与 if-else 的异同:
- 三元运算符可看作 if-else 的简化(三元运算符的效率高)
三元运算符要求必须返回一个结果- if 中的代码块可有多个语句
- 凡是可以使用三元运算符的地方,都可以改写为 if-else,反之不成立
int num = 10;
// 必须接收返回的结果
num = (num > 10) ? 20 : 12;
System.out.println("num = " + num); // 12
// 两个表达式的类型要统一
// (m > n) ? 2 : "n大"; error,找不到合适的类型去接收返回值
int m = 10;
int n = 10;
// 三元运算符的嵌套
String maxStr = (m > n) ? "m" : ((m == n) ? "m == n" : "n");
System.out.println(maxStr);
程序流程控制(重点)
顺序结构
程序从上到下顺序执行
分支结构
根据条件,选择性的执行某段代码,有 if-else 和 switch-case 两种分支语句
if ... else if ... else
- if 或 else if 语句后,只能使用布尔表达式或布尔值作为分支条件来进行分支控制
- if else if 可以嵌套
- if
- if - else 二选一
- if - else if ... - else 多选一
-
从键盘获取不同类型的变量: 使用Scanner类,具体实现步骤如下:
- 导包: import java.util.Scanner;
- Scanner实例化: Scanner scan = new Scanner(System.in);
- 调用Scanner类中的方法来获取指定类型的变量
// 从键盘获取不同类型的变量: 使用Scanner类 // 导包 import java.util.Scanner; class ScannerTest { public static void main(String[] args) { Scanner scan = new Scanner(System.in); // 实例化Scanner类 // nextInt、nextBoolean、nextByte、nextDouble、next ... int num = scan.nextInt(); // 获取键盘输入的数据 System.out.println("num = " + num); } }
switch ... case ... default
结构: switch (expression) { case condition(常量): ... break; ... default: ...;}
- switch 语句后表达式的数据类型只能是 byte、short、char、int、枚举类型(5.0)、String类型(7.0),这六种类型之一
- case 语句后的条件只能是常量,代码块中的 break, 被省略时,会进入陷阱
- default: 相当于 else 语句(备胎),且default结构是可选的、位置也是灵活的(默认位置写在最后)
- 如果switch - case 中多个case条件的执行语句相同则可以合并
switch特性:
- 相同的执行语句,case可以合并
- 灵活使用 break
// 'a' == 97; 'A' == 65
char c1 = 'B';
switch (c1) {
case 'A':
System.out.println("very good");
break;
case 'B':
System.out.println("good");
break;
case 'C':
System.out.println("middle");
break;
case 'D':
System.out.println("tail");
break;
default:
System.out.println("fail");
}
// >= 60 及格,< 60 不及格
int score = 78;
switch(score / 60) {
case 0:
System.out.println("false");
break;
case 1:
System.out.println("true");
break;
default:
System.out.println("return");
}
// 算出当前日期是当年的第几天
// 利用 switch 的特性break
switch (month) {
case 12:
sumDays += 30;
case 11:
sumDays += 31;
// ...
case 3:
sumDays += 28;
case 2:
sumDays += 31;
case 1:
sumDays += day;
}
System.out.println("days" + sumDays);
if-else与switch-case总结:
- 凡是可以使用switch-case的结构,都可以转换为if-else;反之,不成立
- 选择分支结构时,发现既可以使用switch-case又可以使用if-else时,优先使用switch-case,原因是switch-case执行效率稍高
- 三元运算符和switch-case语句都可以转化为if-else语句,反之,不一定成立
- 优先使用三元运算符和switch-case语句,执行效率较高
循环结构
循环结构四要素:
- 初始化条件
- 循环条件 -- boolean类型
- 循环体(有限性)
- 迭代条件
- 说明: 通常情况下,循环结束都是因为2中的循环条件返回了false
根据循环条件,重复性的执行某段代码,有while、do...while、for 三种循环语句
- while循环和for循环可以相互转化,只是初始化条件的作用域不同
- 开发中多使用for和while循环,do-while较少
while
结构: while (布尔表达式/布尔值) { ... }
- 先判断,后执行
- 执行过程: 1 - 2 - 3 - 4 - 2 - 3 - 4 ...
- 经常用于初始化条件复杂的情况
int i1 = 0;
while (i1 < 10) {
++i1;
}
System.out.println("i1 = " + i1); // 10
do while
结构: do {...} while (布尔表达式/布尔值)
- 先执行,后判断
- 执行过程: 1 - 3 - 4 - 2 - 3 - 4 - 2 ...
int i2 =10;
do {
--i2;
} while (i2 >= 0); // 必须加分号 ";"
System.out.println("i2 = " + i2); // -1
for
结构: for (init_state; 逻辑表达式(boolean); iteration_statement) { statement ...}
- 大部分情况下,for 循环可以替代 while、do..while循环
- 初始化变量可以有多个,但数据类型必须相同,因为只能有一个声明语句,因此这些变量必须是相同的数据类型
- 执行过程: 1 - 2 - 3 - 4 - 2 - 3 - 4 ...
- 经常用于数组、字符串等
for (int = 0; i < 10; ++i) {
System.out.println("i = " + i); // 0 1 ... 9
}
// 求两个数的最大公约数,和最小公倍数
import java.util.Scanner;
class ForTest{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("first value m");
int m = scan.nextInt();
System.out.println("second value n");
int n = scan.nextInt();
int min = (m <= n) ? m : n;
// 最大公约数
for (int i = min; i >= 1; --i) {
if (m % i == 0 && n % i == 0) {
System.out.println("max zui da gong yue shu " + i);
break;
}
}
int max = (m >= n) ? m : n;
int maxValue = m * n;
// 最小公倍数
for (int i = max; i <= maxValue; ++i) {
if (i % m == 0 && i % n == 0) {
System.out.println("min zui xiao gong bei shu " + i);
break;
}
}
}
}
// 输出100内的所有质数
// 质数: 从2开始到n-1结束,都不能被这个数n整除;最小的质数是 2
// 获取当前时间的毫秒数 System.currentTimeMillis() 距离1970:01:01:00:00的毫秒数
class ForPrime {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for(int i = 2; i < 100; ++i) {
boolean isFlag = true;
for(int j = 2; j <= Math.sqrt(i); ++j) {
if(i % j == 0) {
isFlag = false;
break;
}
}
if(isFlag) {
System.out.println("is prime " + i);
}
isFlag = true;
}
long endTime = System.currentTimeMillis();
System.out.println((endTime - startTime) + "ms");
}
}
总结:
- 不在循环条件部分限制次数的结构(无限循环): for(;;) === while(true)
- 结束循环的方式: 循环条件部分返回 false 或 在循环体中执行 break,可以共同出现
控制循环结构
Java 为了提高程序的灵活性,提供了
continue和break来控制循环结构
-
使用 break 完全结束一个循环
- break 可以结束其所在的循环
- break 还可以结束本循环的外层循环(当然,外层循环结束,本循环也会结束),结构:
标识符:break 标识符;
// 可以终止 for、while、do while 等循环 for(int i = 10; i > 0; --i) { if(i == 5) { System.out.println("i = " + i); // 5 break; } } // 标识符: outer: for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { if (i == 0 && j == 1) { System.out.println("i = " + i + ", j = " + j); break outer; // 结束外层循环 } } } -
使用 continue 结束本次循环,并进入下一次循环
- continue 的作用是略过当次循环中后面的语句,重新开始新的循环
- 如果将 continue 语句放在单次循环结构的最后一行是没有意义的,因为它没有忽略任何程序语句
- 与 break 类似,continue 也可以紧跟一个
标签,用于直接结束标签所标识循环的当次循环,直接进入下一次循环;格式:标签:continue标签;
// 标识符: outerContinue: for (int i = 0; i < 4; ++i) { for (int j = 0; j < 3; ++j) { if (i < 3) { continue outerContinue; } System.out.println("i = " + i + ", j = " + j); } } // i = 3, j = 0 // i = 3, j = 1 // i = 3, j = 2
问答题
& 和 && 的异同
-
& 逻辑与
-
&& 短路与(推荐使用)
-
相同点:
- 只用同为 true 时,结果才为 true
- 左边为 true 时,右边的表达式才会执行
-
异同点:
- & 的左右两边的表达式都会执行
- && 左边的表达式为true时,才会执行右边的表达式
定义三个变量,获取三个数中的较大值
int i1 = 20;
int i2 = 100;
int i3 = -12;
int max;
if(i1 > i2 && i1 > i3) {
max = i1;
}else if(i2 > i1 && i2 > i3) {
max = i2;
}else {
max = i3;
}
System.out.println("max = " + max); // 100
两个变量值的交换
int i = 10;
int j = 12;
int temp;
temp = i;
i = j;
j = temp;
// 数值型,可以使用位运算符
// k = m ^ n; m = k ^ n = (m ^ n) ^ n;
int i4 = 10;
int i5 = 16;
i4 = i4 ^ i5;
i5 = i4 ^ i5;
i4 = i4 ^ i5;
求一个0-255范围内整数的十六进制,如输出60的十六进制表示
// 使用 Java 内部的方法
String str1 = Integer.toBinaryString(60); // 0011 1100
String str2 = Integer.toHexString(60); // 3c
// 手动实现
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);
获取一个两位数的随机数
// 公式:[a,b] -> (int)(Math.random() * (b - a + 1) + a)
int value = (int)(Math.random() * 90 + 10);
System.out.println(value)
判断是否相同: str.equals("是")
import java.util.Scanner;
class IfExper {
Scanner scan = new Scanner(System.in);
System.out.println("is / no");
String isHandSome = scan.next();
if(isHandSome.equals("is") {
System.out.println("is");
}
}
算法的好坏
- 正确性
- 可读性
- 健壮性
- 高效率与低存储:时间复杂度(更重要)、空间复杂度