1. Java 语言基础
Ch02 Elementary Programming
Identifiers
- 标识符(indentifier) 是由字母、数字、下划线
_和美元符号$组成的字符序列。 - 规则:
- 必须以字母、下划线
_或美元符号$开头,不能以数字开头。 - 不能是 Java 的保留字。
- 不能是
true、false或null。 - 区分大小写。
- 长度没有限制。
- 必须以字母、下划线
Variables
- 变量(variable) 是存储数据的容器。
- 可以在一步中完成变量的声明和初始化。
- Java 变量与 C/C++ 变量的区别
- 在 Java 中,变量的声明和定义没有区分。
- Java 不会为方法中的局部变量赋默认值,必须显式初始化,否则会报 CE。
The final Keyword
- 使用
final修饰变量得到 命名常量(named constant)。- final 变量是不可改变的,只能在初始化的时候被改变一次,但是这个初始化可以在运行时刻初始化,也可以在编译时刻初始化,甚至可以放在构造函数中初始化,而不必在声明的时候初始化。
- 举例:定义类时写
final int x;然后在构造函数中在初始化x = 1;是合法的。
- 举例:定义类时写
- 修饰对象引用时,不能改变引用指向的对象,但不意味着不能改变对象实例的内容。
- final 变量是不可改变的,只能在初始化的时候被改变一次,但是这个初始化可以在运行时刻初始化,也可以在编译时刻初始化,甚至可以放在构造函数中初始化,而不必在声明的时候初始化。
- 使用
final修饰方法表示该方法不能被 重写(override)。 - 使用
final修饰类表示该类不能被继承,里面的所有方法也自动会是final的。
Literals
- 使用
f结尾表示单精度浮点数字面量,使用d结尾表示双精度浮点数字面量。 - 特殊的浮点数值:
Double.POSITIVE_INFINITY:正无穷大。Double.NEGATIVE_INFINITY:负无穷大。Double.NaN:非数值。
Type Casting
- 隐式转换(从小范围到大范围):如
double d = 3; - 显式转换(从大范围到小范围):如
int i = (int)3.9;- 像这样的转换必须显示地写出,否则会 CE。
Ch03 Selections
The boolean Data Type
boolean类型只有两个值:true和false。- 与 C/C++ 不同,整型与布尔型不能直接转换,如当
even是boolean类型时写if (even != 0)会编译错误,if (even)可以通过编译。
if-else statment
else语句采用就近原则,做题时不要被代码缩进欺骗。
switch statement
- 每一个
case下的break语句可以省略,这种情况下会继续执行下一个case的语句。 - 参数的类型限制:
- 在 java 中 switch 后的表达式的类型只能为以下几种:byte、short、char、int、枚举类(在 Java1.6 中是这样),在 java1.7 后支持了对 string 的判断;
- 注意:boolean、long 类型不能作为 switch 参数。
Operator Associativity
- 所有二元运算符都是左结合的:
a – b + c – d等价于((a – b) + c) – d。 - 但是所有赋值运算符都是右结合的:
a = b += c = 5等价于a = (b += (c = 5))。
Ch04 Mathematical Functions, Characters, and Strings
Characters
- Java 中的字符默认采用 UTF-16 编码,每个字符占用 2 字节。
- Comment:对于超出基本字符集(BMP)的字符,会使用代理对(Surrogate Pair)来表示,每个代理对占用 4 字节。
charData Type- 表示单个字符,支持 ASCII 和 Unicode。
- 示例:
char letter = 'A';(ASCII)char letter = '\u0041';(Unicode)
- 可以使用递增或递减操作符获取下一个或前一个字符。
- 示例:
char ch = 'a'; System.out.println(++ch);输出 b。
- 示例:
Character类中的方法:isDigit(ch):判断是否为数字。isLetter(ch):判断是否为字母。isUpperCase(ch):判断是否为大写字母。isLowerCase(ch):判断是否为小写字母。toUpperCase(ch):将字符转换为大写。toLowerCase(ch):将字符转换为小写。
The String Class
- Java 的
String类是不可变类。- 坑点:后面的各种方法都不是在原串上做修改。
- 定义与基本操作
- 使用
String对象表示字符串。 - 示例:
String message = "Welcome to Java";
- 使用
- 常用方法
length():获取字符串长度。- 示例:
"Hello".length()返回 5。
- 示例:
charAt(index):获取指定索引的字符。- 示例:
"Hello".charAt(0)返回H。
- 示例:
concat(s1)或+:拼接字符串。- 示例:
"Hello".concat(" World")返回"Hello World"。
- 示例:
toUpperCase()和toLowerCase():大小写转换。- 示例:
"Hello".toUpperCase()返回"HELLO"。
- 示例:
trim():去除字符串两端的空格。- 示例:
" Hello ".trim()返回"Hello"。
- 示例:

- 字符串比较
equals(s1):比较字符串内容是否相等。- 示例:
"Hello".equals("hello")返回false。
- 示例:
equalsIgnoreCase(s1):忽略大小写比较字符串内容是否相等。- 示例:
"Hello".equalsIgnoreCase("hello")返回true。
- 示例:
compareTo(s1):比较字符串的字典顺序。- 返回值:
- 大于 0:当前字符串大于
s1。 - 等于 0:两字符串相等。
- 小于 0:当前字符串小于
s1。
- 大于 0:当前字符串大于
- 返回值:
compareToIgnoreCase(s1):忽略大小写比较字符串的字典顺序。startsWith(s1):判断字符串是否以s1开头。endsWith(s1):判断字符串是否以s1结尾。
- 子字符串操作
substring(beginIndex):从指定索引开始截取到末尾。substring(beginIndex, endIndex):截取指定范围(左闭右开)的子字符串。- 示例:
"Hello".substring(1, 4)返回"ell"。
- 示例:
- 查找字符或子字符串
indexOf(ch):返回字符首次出现的索引。indexOf(ch, fromIndex):从指定索引开始返回字符首次出现的索引。indexOf(s1):返回子字符串首次出现的索引。indexOf(s1, fromIndex):从指定索引开始返回子字符串首次出现的索引。lastIndexOf(ch):返回字符最后一次出现的索引。- (类似地还有三个这里略。)
- 字符串转数字
Integer.parseInt():将字符串转换为整数。- 示例:
Integer.parseInt("123")返回 123。
- 示例:
Double.parseDouble():将字符串转换为浮点数。- 示例:
Double.parseDouble("3.14")返回 3.14。
- 示例:
- 数字转字符串
String.valueOf():会调用对应基础数据类型的包装类的toString()静态方法。- 可以使用
+ ""- 示例:
123 + ""返回"123"。
- 示例:
String Matching & Replacing & Splitting (Ch10)
replace(oldChar, newChar):字符替换replaceFirst(oldString, newString):子字符串替换,但只替换第一次replaceAll(oldString, newString):子字符串替换split(delimiter): String[]:将字符串按指定串分割成数组- 这里的
match、replace系列、split方法都支持正则表达式。
String Formatting (Ch10)
- 支持
String.format()的静态方法,其中第一个参数是格式化字符串,支持的语法参见下面的 String-Formatting 部分。
Input: The Scanner Class
Scanner sc = new Scanner(System.in);- 使用
Scanner类:nextInt()、nextDouble()、nextFloat()、nextLong()方法:读取整数、浮点数、长整数等等基本数据类型。next()方法:读取单词。从遇到第一个有效字符(非空格、换行符)开始扫描,遇到第一个分隔符或结束符(空格或者换行符\n)时结束。nextLine()方法:读取整行。扫描剩下的所有字符串直到遇到回车为止。(可以从空格开始)。
- 注意:
nextInt()和nextLine()的组合可能导致读取问题(即剩一个空的行末)。解决方法:在nextInt()后添加一个nextLine()。
Formatting Output
TODO:具体还是得看一下课件。
- 使用
printf格式化输出- 格式:
%[index$][标识][最小宽度][.精度]转换符。%:占位符的起始字符,若要在占位符内部使用%,则需要写成%%。[index$]:位置索引从 1 开始计算,用于指定对索引相应的实参进行格式化并替换掉该占位符。[标识]:用于增强格式化能力,可同时使用多个[标识],但某些标识是不能同时使用的。[最小宽度]:用于设置格式化后的字符串最小长度,若使用[最小宽度]而无设置[标识],那么当字符串长度小于最小宽度时,则以左边补空格的方式凑够最小宽度。[.精度]:对于浮点数类型格式化使用,设置保留小数点后多少位。转换符:用于指定格式化的样式,和限制对应入参的数据类型。
- 常用转换符
%b:布尔值。%c:字符。%s:字符串。%d:整数。%f:浮点数。%e:科学计数法(4.556000e+01)。- 日期和时间:
%tF:完整日期(如 2024-12-17)。%tT:完整时间(如 15:45:14)。- 还有各种,以
%t开头。
- 标识
-:左对齐。0:用零填充。,:千位分隔符。+:显示正负号。
- 示例
- 将整数补零:
String.format("%04d", 5)返回"0005"。 - 千位分隔符:
String.format("%,d", 1000000)返回"1,000,000"。
- 将整数补零:
- 格式:
Ch05 Loops
do-while Loop
- 基本结构:
do { // Loop body; Statement(s); } while (loop-continuation-condition); - 特点:至少执行一次循环体,然后再检查条件。
Break with Tag
- 使用带标签的
break语句可以跳出多层嵌套循环。- 示例:
outer: for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (j == 2) break outer; // 跳出 outer 循环 System.out.println("i = " + i + ", j = " + j); } }
- 示例:
- 可以将标签用到任意语句块中(即大括号括起来的一段语句),使用带标签的
break语句可以跳出该语句块,即使这个语句块不是循环体。
For-in
- Java 5 引入了用于数组和容器的 for-in 语法,这类似于 C++ 14 的 range-based for 语法。
- 示例:
int[] numbers = {1, 2, 3, 4, 5}; for (int number : numbers) { System.out.println(number); }
- 示例:
Ch06 Methods
Methods
- 方法(method) 是一组语句的集合,用于完成某个特定的操作。通过方法可以实现代码的复用、模块化和易维护性。
- 方法签名(method signature) 定义为方法名和参数列表的组合,它是方法的唯一标识。
Formal & Actual Parameters
- 形式参数(formal parameter) 是方法头中定义的变量,用于接收调用方法时传递的值。
- 实际参数(actual parameter) 是在调用方法时传递给形式参数的值。
- Java 中的参数传递是 按值传递(pass by value) 的,即将实际参数的值复制一份传递给方法。
- 即方法内对参数的修改不会影响方法外的变量。
Overloading
| 特性 | Override(方法重写) | Overload(方法重载) |
|---|---|---|
| 定义 | 子类重新定义父类的方法,实现不同的行为。 | 同一个类中定义多个同名方法,参数列表不同。 |
| 方法名 | 必须相同。 | 必须相同。 |
| 参数列表 | 必须完全相同。 | 必须不同(数量、类型或顺序)。 |
| 返回值类型 | 必须相同或是父类返回值类型的子类型(协变返回类型)。 | 无要求(不会影响重载)。 |
| 访问修饰符 | 不能更严格。 | 无限制,可以改变。 |
| 关键字 | 必须加 @Override 注解(推荐)。 | 不需要 @Override 注解。 |
| 静态方法 | 不能重写静态方法。 | 静态方法可以重载。 |
| 多态性 | 支持运行时多态(动态绑定)。 | 不支持运行时多态(编译时绑定)。 |
| 使用场景 | 用于继承关系中,子类修改父类的行为。 | 用于同一类中方法的灵活性,处理不同的参数情况。 |
- 方法的 重载(overload) 是指在同一个类中定义多个同名方法,但参数列表不同。
- 注意区分 overload 和 override。
- 可以重载静态方法,但不能重写静态方法。
- 模糊调用(ambiguous invocation):在方法调用时,编译器可能发现有多个方法匹配,无法确定哪一个是最具体的,这种时候会直接 CE。
- 原因:
- 方法重载时,多个方法的参数列表可能存在一定的重叠,导致编译器无法确定调用哪个方法。
- 方法调用中涉及自动类型转换或可变参数时,可能会有多个方法同时符合调用条件。
- 举例:如果有
print(int); print(double);两个方法,则在print(1);时会认为前者更具体而不会报错,但如果同时有print(int, double);和print(double, int);两个方法,则print(1, 1);时就无法确定调用哪个方法更具体,从而会报错。
- 原因:
Ch07 Single-Dimensional Arrays
Single-Dimensional Arrays
- 声明数组
- 语法:
datatype[] arrayRefVar;datatype arrayRefVar[];(不推荐)
- 语法:
- 创建数组
- 语法:
arrayRefVar = new datatype[arraySize];- 示例:
myList = new double[10];
- 创建时会自动设定为默认值:
- 数值基本类型自动设定为
0,字符类型默认为\u0000,布尔类型默认为false。 - 对象引用类型默认为
null。
- 数值基本类型自动设定为
- 语法:
- 使用
arrayRefVar.length获取数组大小。- 数组一旦创建,大小就固定不能改变。
- 数组初始化器(array initializer):使用时必须要在一个语句中完成数组的声明、创建和初始化,否则会导致 CE。
- 举例:
double[] myList = {1.9, 2.9, 3.4, 3.5}; - 可以用
new int[]{3, 1, 5, 2, 4}的语法用数组初始化器创建 匿名数组(anonymous array)。
- 举例:
- Java 数组的内存分配在堆上。而在 C 中,使用
int a[100]创建的数组分配在栈上,使用int *a = new int[100];创建的数组分配在堆上。 - 边界检查:Java 的
[]操作符会检查数组边界。 - 拷贝数组:不会重新创建数组,而是直接将引用复制。
- 正确的拷贝数组方式:
- 重新创建一个并依次赋值
- 使用
System.arraycopy:System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);。 - 使用
Arrays.copyOf:int[] copiedArray = Arrays.copyOf(sourceArray, sourceArray.length);
- 正确的拷贝数组方式:
Ch08 Multidimensional Arrays
Two-dimensional Arrays
- 声明与创建:
// 声明数组引用变量 dataType[][] refVar; refVar = new dataType[10][10]; // 声明和创建结合 dataType[][] refVar = new dataType[10][10]; // 另一种语法 dataType refVar[][] = new dataType[10][10];- 多维数组的创建时应从左到右指定维数,未指定的维数不会自动创建内容,需要再手动创建。
- 即
int a[][] = new int[3][0]和new int[3][3]都是合法的,但是前者要再使用a[0] = new int[3]才能创建第二维的内容。
- 即
- 多维数组的创建时应从左到右指定维数,未指定的维数不会自动创建内容,需要再手动创建。
- Java 的数组每一维可以有不同的大小,大小不同的数组称为 不规则数组(ragged array)。
杂项
System.currentTimeMillis()返回自 1970 年 1 月 1 日以来的毫秒数。- Java 语言的
public static void main(String args[])命令行参数中,从第一个位置开始存储命令行参数(即args[0]),程序名没有存储在args中。 - Java 中不能在 嵌套 代码块中重复声明同名变量,这点与 C/C++ 不同。
- 静态导入
import static:可以引入类的静态成员,如import static java.lang.Math.PI后可以直接用PI而不用Math.PI。
java.lang.Math (Ch04)
- 常用常量
Math.PI:圆周率。Math.E:自然对数的底。
- 常用方法
- 三角函数:
Math.sin、Math.cos、Math.tan、Math.toRadians等。 - 指数函数:
Math.exp、Math.log、Math.log10、Math.pow、Math.sqrt。 - 四舍五入方法:
Math.ceil、Math.floor、Math.rint、Math.round。Math.rint()方法是向最接近的整数取整,如果出现 x.5 的情况则向 x 和 x+1 中的偶数取整。
- 最值和绝对值:
Math.max、Math.min、Math.abs。 - 随机数生成:
Math.random()生成 的随机数。
- 三角函数:
java.utils.Arrays (Ch07)
copyOf(array, newLength)静态方法:拷贝数组。binarySearch(array, key)静态方法:二分搜索(要求数组有序)。sort(array)静态方法:将数组排序。
java.util.Date (Ch09)
- 构造函数:
Date():构造一个表示当前时间的 Date 对象。Date(elapseTime: long):构造一个 Date 对象,表示自 1970 年 1 月 1 日 GMT 以来指定毫秒数的时间。
- 方法:
toString() : String:返回表示日期和时间的字符串。(例:Sun Mar 09 13:50:19EST 2003)getTime() : long:返回自 1970 年 1 月 1 日 GMT 以来的毫秒数。setTime(elapseTime: long) : void:设置对象的新时间。
java.util.Random (Ch09)
- 构造函数:
Random():使用当前时间作为种子构造一个 Random 对象。Random(seed: long):使用指定的种子构造一个 Random 对象。
- 方法:
nextInt() : int:返回一个随机的 int 值。nextInt(n: int) : int:返回一个 0(含)到 n(不含)之间的随机 int 值。nextLong() : long:返回一个随机的 long 值。nextDouble() : double:返回一个 0.0(含)到 1.0(不含)之间的随机 double 值。nextFloat() : float:返回一个 0.0F(含)到 1.0F(不含)之间的随机 float 值。nextBoolean() : boolean:返回一个随机的 boolean 值。
Comments