☕ 第三章 面向对象(上)

3.8 本章小结

📄 一句话概括

本章不写新知识点,只干一件事:把 3.1~3.7 七节拧成一股绳——从"类是图纸"的思想出发,到会造(new)、会藏(private)、会生(构造方法)、分清"我"(this)、按时出场(代码块)、归属类(static),最后给出复习装备:速查表、七大名坑和毕业自检。


1. 七节串成一条线

3.1 思想        类 = 图纸,对象 = 实物(属性=变量,行为=方法)
  ↓
3.2 类与对象    class 画图纸 → new 造实物 → 点号 . 下指令
  ↓             (栈存钥匙,堆住实物)
3.3 封装性      private 上锁 + getter/setter 门卫 + this 分身
  ↓             (真价值:把变化圈在一处)
3.4 构造方法    对象出生即带设定;默认构造写了就收回;无参+带参成对
  ↓
3.5 this关键字  this = 当前对象本人(隐形参数);this(...) 构造互调
  ↓
3.6 代码块      静态一次 → 构造块每次 → 构造方法收尾
  ↓
3.7 static      属于类,不属于对象;全类一份;不 new 也能用

一条暗线贯穿全章:对象变量存的是地址(钥匙),实物住堆里——2.7 数组、3.2 对象、3.7 静态引用,全是这一套。第五章会正式收网。


2. 核心概念速查(14 条,考前 3 分钟扫完)

# 概念 一句话
1 类 图纸:定义有哪些属性、哪些行为,本身没有具体值
2 对象 照图纸造出的实物,每个属性有真值,new 一次造一个
3 new 的三步 堆里开格子 → 构造方法自动上岗 → 把地址交回(钥匙)
4 对象.成员 点号:取属性用 c1.brand,喊行为用 c1.run()
5 空指针 NPE 钥匙是 null 还去开车 → NullPointerException,新手第一大异常
6 双钥匙一辆车 Car b = a; 复制的是地址,改 b 等于改 a
7 private 私有上锁,外界点号直取直接编译报错
8 getter/setter 两扇受控的门;命名 getXxx/setXxx(boolean 用 isXxx)是全圈统一惯例
9 this 当前对象本人,方法自带的隐形参数;参数撞名时 this. 必须写
10 构造方法 名字=类名、返回值整栏不写、new 时自动执行
11 默认构造 一个构造都没写时免费送;写了任何一个就当场收回
12 this(...) 构造互调:必须第一行、只能调一次、禁止循环互调
13 三种代码块 局部(方法内)/ 构造(每次 new)/ 静态(类第一次用,仅一次)
14 static 属于类不属于对象;静态方法没有 this;main 必须 static

3. 代码模板速查(标准写法,四段背熟能救命)

① 标准类骨架(封装三件套 + 构造)

public class Student {
    private String name;   // 属性全部 private
    private int score;

    public Student() {                          // 无参构造(兜底)
        this("未知", 0);                         // 转发给全参,安检只写一处
    }
    public Student(String name, int score) {    // 全参构造
        this.name = name;
        setScore(score);                        // 走 setter 过安检
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getScore() { return score; }
    public void setScore(int score) {           // 带安检的门卫
        if (score >= 0 && score <= 100) {
            this.score = score;
        } else {
            System.out.println("分数必须在 0~100 之间");
        }
    }
}

② 造对象 + 下指令

Student s = new Student("波仔", 95);  // 出生即带设定
s.setScore(101);                       // 被门卫拦下
System.out.println(s.getName());      // 点号取属性

③ 构造互调链(无参 → 全参,单向)

public Employee() { this("临时工", 0); }        // 转发前台
public Employee(String name, double salary) {   // 唯一干活的
    this.name = name;
    this.salary = salary;
}

④ 三块执行顺序的验证模板

static { System.out.println("① 静态块:全程序仅一次"); }
{ System.out.println("② 构造块:每次 new 都先于构造方法"); }
public Game() { System.out.println("③ 构造方法:收尾"); }
// 输出顺序永远:① → ② → ③,与书写位置无关

4. 本章名坑回顾(七个,个个真会撞)

⚠️ 坑 1:`Car c1;` 不 new 就用

空指针异常。钥匙是空的,车在哪?Java 里所有"NullPointerException",第一反应都是:这把钥匙 new 过没有?

⚠️ 坑 2:`brand = brand;` 漏写 this

编译、运行都不报错,但属性永远收不到值(参数赋参数)。比报错难查十倍——参数和属性撞名时,this. 必须写。

⚠️ 坑 3:构造方法写上 void

public void Car() {...} 变成了撞名的普通方法,不参与 new。"没有返回值" ≠ "void"——构造方法返回值整栏什么都不写。

⚠️ 坑 4:写了带参构造,`new Car()` 报错

默认构造"写了任何一个就当场收回"。解法:无参 + 带参成对写。

⚠️ 坑 5:`this(...)` 不在第一行 / 循环互调

两条都是编译报错。互调还会报"递归构造器调用"——构造链必须单向,终点是那个真正干活的。

⚠️ 坑 6:IDEA 生成的 setter 没安检

Alt + Insert 生成的是裸 setter。业务规则(0~100 之类)永远手动补,而且构造方法里的赋值建议转发给 setter,安检只写一处。

⚠️ 坑 7:静态方法里碰实例成员

"无法从静态上下文中引用非静态变量"。三条 static 限制(不能碰实例属性 / 没有 this / 静态块碰不了实例成员)是同一个原因:对象可能还没出生。

坑的规律:第一章的坑是工具层(编译器帮你抓),第二章开始出现逻辑层(程序照跑结果不对),本章的坑里出现了两个编译报错但报错信息晦涩的类型(递归构造器、静态上下文)——看懂报错原文,比背坑本身更有用。


5. 三大特性进度条

封装(3.3)✅ ──→ 继承(待学)──→ 多态(待学)

本章只点亮了第一盏。继承拿到的是"白得的属性和方法",多态拿到的是"同一句话不同反应"——它们俩都要靠封装打的地基(访问控制)。后面的章节见。


6. 与前面章节的连线(复习用)

本章知识点 承接哪篇 连的是什么
属性 / 行为 2.2 变量 / 2.6 方法 面向对象没有新语法,只是把两者装进类
栈钥匙堆实物 2.7 数组传地址 对象与数组同构:变量存地址,实物住堆
car.price = -99999 不报错 2.3 运算符 编译器只管语法,业务规则要自己设门卫
构造互调 / 转发 3.4 → 3.5 无参构造当转发前台,赋值安检只写一处
静态块仅一次 1.4 类加载 类第一次被使用时加载,只加载一次
static 与 main 1.3 / 1.4 JVM 不 new 就要喊入口,所以 main 必须 static

7. 毕业自检(5 题,合上笔记答)

❓ Q1:`new Car("宝马", 200000)` 这一行,JVM 在背后做了哪三件事?

① 堆里开格子(按类的图纸分配空间,属性先放默认值)→ ② 构造方法自动上岗(把"宝马"和 200000 装进属性)→ ③ 把堆里的地址交回,赋给变量 c1(钥匙)。记住顺序:先有车,再设置,后给钥匙。

❓ Q2:下面两个 price 各是谁?漏了 this 会发生什么?
public void setPrice(double price) {
    this.price = price;
}

左边 this.price 是当前对象的属性,右边 price 是参数。漏写 this 变成 price = price;——参数赋给自己,属性分毫未动,且编译运行都不报错,是最隐蔽的一类 bug。

❓ Q3:为什么"无参构造里转发给全参构造"比"两处各写一遍赋值"更好?

赋值和安检规则只写一处(全参构造 / setter),将来改规则(比如加日志、改分数上限)只动一个地方,全类生效。这就是 3.3 说的封装真价值:把变化圈在一处。写两遍的版本迟早改漏一处。

❓ Q4:`Game` 类里有静态块、构造块、构造方法各一个,`main` 里 `new Game(); new Game();` 共输出几行?顺序?

5 行:静态块 1 行(类第一次被使用,仅一次)+ 构造块 2 行(每次 new 都跑)+ 构造方法 2 行。顺序:①静态 → ②构造块 → ③构造方法 → ②构造块 → ③构造方法。与书写位置无关。

❓ Q5(毕业大题):独立写一个 `Book` 类:属性 name(String)、price(double),要求 ① 全部 private;② 无参构造(兜底"未知书名"、0 元)转发给全参;③ 全参构造里价格走 setter 过 0~500 安检;④ getter/setter 齐全。再写测试类造两本书,其中一本故意传 -9.9 看被拦。

参考骨架就是本文第 3 节模板 ①② 的合体。合格标准:不看任何笔记 20 分钟内写完且编译运行通过;优秀标准:能顺口说出每一段在防哪个坑(安检在门卫、构造转发收拢变化、private 防裸奔)。写不出来就翻回 3.3 / 3.4 / 3.5,看完合上再写,直到默出。


8. 下一步学什么


相关笔记