1. Java 语言基础

Ch02 Elementary Programming

Identifiers

  • 标识符(indentifier) 是由字母、数字、下划线 _ 和美元符号 $ 组成的字符序列。
  • 规则
    1. 必须以字母、下划线 _ 或美元符号 $ 开头,不能以数字开头。
    2. 不能是 Java 的保留字。
    3. 不能是 truefalsenull
    4. 区分大小写。
    5. 长度没有限制。

Variables

  • 变量(variable) 是存储数据的容器。
  • 可以在一步中完成变量的声明和初始化。
  • Java 变量与 C/C++ 变量的区别
    • 在 Java 中,变量的声明和定义没有区分。
    • Java 不会为方法中的局部变量赋默认值,必须显式初始化,否则会报 CE

The final Keyword

  • 使用 final 修饰变量得到 命名常量(named constant)
    • final 变量是不可改变的,只能在初始化的时候被改变一次,但是这个初始化可以在运行时刻初始化,也可以在编译时刻初始化,甚至可以放在构造函数中初始化,而不必在声明的时候初始化。
      • 举例:定义类时写 final int x; 然后在构造函数中在初始化 x = 1; 是合法的
    • 修饰对象引用时,不能改变引用指向的对象,但不意味着不能改变对象实例的内容。
  • 使用 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 类型只有两个值:truefalse
  • 与 C/C++ 不同,整型与布尔型不能直接转换,如当 evenboolean 类型时写 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 字节。
  • char Data 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
    • 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[]:将字符串按指定串分割成数组
  • 这里的 matchreplace 系列、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.arraycopySystem.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);
      • 使用 Arrays.copyOfint[] 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.sinMath.cosMath.tanMath.toRadians 等。
    • 指数函数Math.expMath.logMath.log10Math.powMath.sqrt
    • 四舍五入方法Math.ceilMath.floorMath.rintMath.round
      • Math.rint() 方法是向最接近的整数取整,如果出现 x.5 的情况则向 x 和 x+1 中的偶数取整。
    • 最值和绝对值Math.maxMath.minMath.abs
    • 随机数生成
      • Math.random() 生成 [0.,1.)[0., 1.) 的随机数。

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