本文总结 Core Java 书中的:第 3 章 Java 的基本程序设计结构、第 4 章 对象与类、第 5 章 继承。

3 Java 的基本程序设计结构

3.3 数据类型

  • Java 有 8 种基本类型(primitive type):4 种整型、2 种浮点类型、char、boolean
  • Java 7 起可用下划线增强数字可读性:1_000_000
  • 浮点数不适用于金融计算(二进制无法精确表示 1/10),应使用 BigDecimal

3.4 变量

  • $ 是合法字符,但仅用于编译器生成的名字,不要在代码中使用

3.6 字符串

  • String 是不可变的(immutable)
  • 不要用 == 比较字符串:只有字符串常量是共享的,+substring 产生的结果不共享

3.10 数组

  • 数组赋值是引用拷贝,两个变量指向同一数组:
int[] luckyNumbers = smallPrimes;
luckyNumbers[5] = 12; // smallPrimes[5] 也变成 12
  • 值拷贝使用 Arrays.copyOf
int[] copiedNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);

彩票抽奖示例(从 1~n 中随机取 k 个不重复数字):

int[] harr = new int[n];
for (int i = 0; i < n; i++) {
    harr[i] = i + 1;
}

int[] result = new int[k];
for (int i = 0; i < k; i++) {
    int random = (int) (Math.random() * n);
    result[i] = harr[random];
    harr[random] = harr[n - 1]; // 用最后元素替换已取元素
    n--;
}
Arrays.sort(result);

关键点:每次取的是下标而非值,通过缩小有效范围避免重复抽取。

4 对象与类

4.1 面向对象程序设计概述

关系含义示例
依赖 (uses-a)一个类的方法操纵另一个类的对象Order 使用 Account
聚合 (has-a)类 A 的对象包含类 B 的对象Order 包含 Item
继承 (is-a)类 A 扩展类 BRushOrder 继承 Order

设计原则:尽量减少类之间的依赖,降低耦合度。

4.2 使用预定义类

  • 对象变量不是对象,只是对象的引用
  • Date deadline; 只声明了变量,未引用任何对象
  • new 操作符返回的是引用
  • 可设置为 null 表示不引用任何对象

4.3 用户自定义类

构造器特点:

  • 与类同名、无返回值
  • 可有多个(重载)
  • 伴随 new 调用

封装原则:

  • 实例域用 private
  • 不要返回可变对象的引用,应返回 clone
// 错误:破坏封装
public Date getHireDay() {
    return hireDay;
}

// 正确:返回副本
public Date getHireDay() {
    return (Date) hireDay.clone();
}

关于 final

  • 适用于基本类型或不可变类
  • 对可变对象,final 只保证引用不变,对象内容仍可修改:
private final Date hireDate; // 引用不可变,但 hireDate.setTime() 仍可调用

4.4 静态域与静态方法

  • 静态域属于类,所有实例共享:
class Employee {
    private static int nextId = 1; // 所有实例共享
    private int id;                // 每个实例独有
}
  • 静态方法建议用类名调用:Employee.getNextId()
  • 每个类可有 main 方法用于单元测试

4.5 方法参数

Java 始终是按值调用

  • 不能修改基本类型参数
  • 可以改变对象参数的状态
  • 不能让对象参数引用新对象

常见误解:Java 对象采用引用传递?实际上不是。反例:

public static void swap(Employee x, Employee y) {
    Employee temp = x;
    x = y;
    y = temp;
}

Employee a = new Employee("Alice", 70000);
Employee b = new Employee("Bob", 60000);
swap(a, b);
// 结果:a 仍是 Alice,b 仍是 Bob

原因:调用 swap 时,a 将引用的副本传给 x,b 将引用的副本传给 y。方法内交换的只是 x、y 的指向,方法外的 a、b 不受影响。

4.6 对象构造

  • 方法签名 = 方法名 + 参数类型(不含返回类型)
  • 无构造器时系统提供默认构造器(域设为默认值)
  • 提供了构造器后,默认构造器不再自动生成
  • 建议显式初始化实例域:
class Employee {
    private String name = "";
    private double salary = 0;
}

4.10 类设计技巧

  1. 保证数据私有
  2. 一定要初始化数据
  3. 不要过多使用基本类型,用类封装
  4. 不是所有域都需要 getter/setter
  5. 职责过多的类要分解
  6. 命名要体现职责

5 继承

5.1 类、超类和子类

this vs super

  • super 不是对象引用,只是调用超类的关键字
  • 两者调用构造器都必须是第一条语句,不能同时出现

多态与动态绑定:

  • 多态:对象变量可指向多种实际类型
  • 动态绑定:运行时自动选择调用哪个方法

数组协变的陷阱:

Manager[] managers = new Manager[10];
Employee[] staff = managers; // 合法,但危险
staff[0] = new Employee(...); // 编译通过,运行时出错

静态绑定 vs 动态绑定:

特性静态绑定动态绑定
时机编译时运行时
适用private/static/final 方法、构造器虚方法(可重写的方法)
依据类信息对象信息
对应重载 (Overload)重写 (Override)

方法表:虚拟机为每个类预先创建方法表,避免每次调用都搜索。

访问修饰符:

修饰符可见范围
private本类
默认本包
protected本包 + 所有子类
public所有类

5.2 Object:所有类的超类

equals 方法标准模板:

public boolean equals(Object otherObject) {
    // 1. 同一引用
    if (this == otherObject) return true;
    // 2. null 检查
    if (otherObject == null) return false;
    // 3. 类型检查(子类语义不同用 getClass,相同用 instanceof)
    if (getClass() != otherObject.getClass()) return false;
    // 4. 类型转换
    Employee other = (Employee) otherObject;
    // 5. 比较域(基本类型用 ==,对象用 equals)
    return Objects.equals(name, other.name)
        && salary == other.salary
        && Objects.equals(hireDay, other.hireDay);
}

References