Java Fundamentals

本篇笔记介绍了 Java 编程的基础知识,包括标识符规则、变量声明与初始化、final 关键字的使用、字面量与类型转换、选择语句(if-else、switch)、运算符结合性、字符与字符串处理、输入输出、循环语句、方法定义与重载、数组的创建与使用等内容。特别强调了 Java 与 C/C++ 的一些重要区别,如变量初始化要求、布尔类型使用规则等。同时详细讲解了 String 类的常用方法、Scanner 类的输入处理、格式化输出、方法重载的规则以及数组的内存分配特点。(由 claude-3.5-sonnet 生成摘要)

1. Ch02 Elementary Programming

1.1. Identifiers

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

1.2. Variables

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

1.3. The final Keyword

  • 使用 final 修饰变量得到 命名常量(named constant)
    • final 变量是不可改变的,只能在初始化的时候被改变一次,但是这个初始化可以在运行时刻初始化,也可以在编译时刻初始化,甚至可以放在构造函数中初始化,而不必在声明的时候初始化。
      • 举例:定义类时写 final int x; 然后在构造函数中在初始化 x = 1; 是合法的
    • 修饰对象引用时,不能改变引用指向的对象,但不意味着不能改变对象实例的内容。
  • 使用 final 修饰方法表示该方法不能被 重写(override)
  • 使用 final 修饰类表示该类不能被继承,里面的所有方法也自动会是 final 的。

1.4. Literals

  • 使用 f 结尾表示单精度浮点数字面量,使用 d 结尾表示双精度浮点数字面量。
  • 特殊的浮点数值:
    • Double.POSITIVE_INFINITY:正无穷大。
    • Double.NEGATIVE_INFINITY:负无穷大。
    • Double.NaN:非数值。

1.5. Type Casting

  • 隐式转换(从小范围到大范围):如 double d = 3;
  • 显式转换(从大范围到小范围):如 int i = (int)3.9;
    • 像这样的转换必须显示地写出,否则会 CE

2. Ch03 Selections

2.1. The boolean Data Type

  • boolean 类型只有两个值:truefalse
  • 与 C/C++ 不同,整型与布尔型不能直接转换,如当 evenboolean 类型时写 if (even != 0) 会编译错误,if (even) 可以通过编译。

2.2. if-else statment

  • else 语句采用就近原则,做题时不要被代码缩进欺骗

2.3. switch statement

  • 每一个 case 下的 break 语句可以省略,这种情况下会继续执行下一个 case 的语句。
  • 参数的类型限制
    • 在 java 中 switch 后的表达式的类型只能为以下几种:byte、short、char、int、枚举类(在 Java1.6 中是这样),在 java1.7 后支持了对 string 的判断;
    • 注意:boolean、long 类型不能作为 switch 参数。

2.4. Operator Associativity

  • 所有二元运算符都是左结合的a – b + c – d 等价于 ((a – b) + c) – d
  • 但是所有赋值运算符都是右结合的a = b += c = 5 等价于 a = (b += (c = 5))

3. Ch04 Mathematical Functions, Characters, and Strings

3.1. 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):将字符转换为小写。

3.2. 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"

3.2.1. String Matching & Replacing & Splitting (Ch10)

  • replace(oldChar, newChar):字符替换
  • replaceFirst(oldString, newString):子字符串替换,但只替换第一次
  • replaceAll(oldString, newString):子字符串替换
  • split(delimiter): String[]:将字符串按指定串分割成数组
  • 这里的 matchreplace 系列、split 方法都支持正则表达式

3.2.2. String Formatting (Ch10)

  • 支持 String.format() 的静态方法,其中第一个参数是格式化字符串,支持的语法参见下面的 String-Formatting 部分。

3.3. Input: The Scanner Class

  • Scanner sc = new Scanner(System.in);
  • 使用 Scanner 类:
    • nextInt()nextDouble()nextFloat()nextLong() 方法:读取整数、浮点数、长整数等等基本数据类型。
    • next() 方法:读取单词。从遇到第一个有效字符(非空格、换行符)开始扫描,遇到第一个分隔符或结束符(空格 或者换行符 \n)时结束
    • nextLine() 方法:读取整行。扫描剩下的所有字符串直到遇到回车为止。(可以从空格开始)
  • 注意:nextInt()nextLine() 的组合可能导致读取问题(即剩一个空的行末)。解决方法:在 nextInt() 后添加一个 nextLine()

3.4. Formatting Output

TODO:具体还是得看一下课件。

  • 使用 printf 格式化输出
    • 格式:%[index$][标识][最小宽度][.精度]转换符
    • 常用转换符
      • %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"

4. Ch05 Loops

4.1. do-while Loop

  • 基本结构:
    do {
        // Loop body;
        Statement(s);
    } while (loop-continuation-condition);
  • 特点:至少执行一次循环体,然后再检查条件。

4.2. 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 语句可以跳出该语句块,即使这个语句块不是循环体。

4.3. 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);
      }

5. Ch06 Methods

5.1. Methods

  • 方法(method) 是一组语句的集合,用于完成某个特定的操作。通过方法可以实现代码的复用、模块化和易维护性。
  • 方法签名(method signature) 定义为方法名和参数列表的组合,它是方法的唯一标识。

5.2. Formal & Actual Parameters

  • 形式参数(formal parameter) 是方法头中定义的变量,用于接收调用方法时传递的值。
  • 实际参数(actual parameter) 是在调用方法时传递给形式参数的值。
  • Java 中的参数传递是 按值传递(pass by value) 的,即将实际参数的值复制一份传递给方法
    • 即方法内对参数的修改不会影响方法外的变量。

5.3. Overloading

  • 方法的 重载(overload) 是指在同一个类中定义多个同名方法,但参数列表不同
    • 注意区分 overload 和 override。
    • 可以重载静态方法,但不能重写静态方法。
  • 模糊调用(ambiguous invocation):在方法调用时,编译器可能发现有多个方法匹配,无法确定哪一个是最具体的,这种时候会直接 CE
    • 原因:
      • 方法重载时,多个方法的参数列表可能存在一定的重叠,导致编译器无法确定调用哪个方法。
      • 方法调用中涉及自动类型转换或可变参数时,可能会有多个方法同时符合调用条件。
    • 举例:如果有 print(int); print(double); 两个方法,则在 print(1); 时会认为前者更具体而不会报错,但如果同时有 print(int, double);print(double, int); 两个方法,则 print(1, 1); 时就无法确定调用哪个方法更具体,从而会报错。

6. Ch07 Single-Dimensional Arrays

6.1. 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);

7. Ch08 Multidimensional Arrays

7.1. 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)

8. 杂项

  • 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

8.1. 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.) 的随机数。

8.2. java.utils.Arrays (Ch07)

  • copyOf(array, newLength) 静态方法:拷贝数组。
  • binarySearch(array, key) 静态方法:二分搜索(要求数组有序)。
  • sort(array) 静态方法:将数组排序。

8.3. 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:设置对象的新时间。

8.4. 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 值。

评论

TABLE OF CONTENTS

1. Ch02 Elementary Programming
1.1. Identifiers
1.2. Variables
1.3. The final Keyword
1.4. Literals
1.5. Type Casting
2. Ch03 Selections
2.1. The boolean Data Type
2.2. if-else statment
2.3. switch statement
2.4. Operator Associativity
3. Ch04 Mathematical Functions, Characters, and Strings
3.1. Characters
3.2. The String Class
3.3. Input: The Scanner Class
3.4. Formatting Output
4. Ch05 Loops
4.1. do-while Loop
4.2. Break with Tag
4.3. For-in
5. Ch06 Methods
5.1. Methods
5.2. Formal & Actual Parameters
5.3. Overloading
6. Ch07 Single-Dimensional Arrays
6.1. Single-Dimensional Arrays
7. Ch08 Multidimensional Arrays
7.1. Two-dimensional Arrays
8. 杂项
8.1. java.lang.Math (Ch04)
8.2. java.utils.Arrays (Ch07)
8.3. java.util.Date (Ch09)
8.4. java.util.Random (Ch09)