Java 面向对象基础总结

作者:没有四次元口袋的蓝胖
日期:2026-06-05
标签:Java, 面向对象


一、面向对象思想

核心理念

用"对象"来描述和解决问题:谁来做、做什么,而非怎么一步步做。

思维四步法

  1. 找对象(名词 → 类)→ 2. 定属性(形容词 → 成员变量)→ 3. 定行为(动词 → 方法)→ 4. 建关系(继承/组合/调用)

三大特征

特征 一句话 比喻
封装 隐藏细节,暴露接口 自动挡汽车——踩油门就行
继承 子类复用父类能力 儿子继承爸爸的姓和房子
多态 同一指令,不同表现 “叫一声”——猫喵、狗汪

二、类与对象

类 = 模板,对象 = 实例(设计图纸 vs 造出来的车)

public class Student {
    String name;   // 属性
    int age;

    public void study() { System.out.println(name + "正在学习"); }  // 行为
}

内存模型

  • :存放引用(stu1stu2
  • :存放对象实例(属性值 + 方法引用)
  • 引用赋值 stu2 = stu1 是共享同一对象,不是拷贝

三、构造方法

创建对象时自动调用,用于初始化。

特点 说明
方法名 = 类名 public Student()
无返回值类型 void 都没有
可重载 无参 / 有参可并存
不写时 系统默认提供无参构造

⚠️ 写了有参构造后,无参构造消失! Spring 等框架依赖无参构造,务必补上。

public Student() {}                              // 无参
public Student(String name) { this.name = name; }  // 有参

四、this 关键字

this = 当前对象的引用。

用法 示例 场景
区分变量 this.name = name 参数与成员变量同名
调用构造 this("未知", 0) 构造方法第一行,调用其他构造
返回自身 return this 链式调用

this(...)super(...) 互斥,不能同时出现在同一构造方法中。


五、方法重载(Overload)

同一个类,方法名相同,参数列表不同。

规则 说明
方法名 必须相同
参数列表 必须不同(类型/个数/顺序)
返回值 无关——仅返回值不同不算重载
public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; }
public int add(int a, int b, int c) { return a + b + c; }

六、封装

private + getter/setter + 校验,隐藏细节,暴露安全接口。

public class Student {
    private int age;

    public void setAge(int age) {
        if (age < 0 || age > 150) {
            System.out.println("年龄不合法");
            return;
        }
        this.age = age;
    }

    public int getAge() { return age; }
}

四种访问权限

修饰符 同一类 同一包 不同包子类 不同包非子类
private
缺省
protected
public

封装典型做法:成员变量 private,方法 public,从严到宽按需开放。


七、继承

子类复用父类,体现 is-a 关系。Java 单继承,可多层继承,默认继承 Object

class Dog extends Animal {
    public void bark() { System.out.println(name + "汪汪叫"); }
}
  • 子类获得父类非 private 的属性和方法
  • 子类不可获父类的构造方法和 private 成员
  • is-a 用继承,has-a 用组合(Car has a Wheel → 组合,不是继承)

八、super 关键字

super = 父类的引用。

用法 示例 说明
访问父类变量 super.name 子父类同名变量时区分
调用父类方法 super.eat() 重写后仍需调用父类版本
调用父类构造 super(name) 子类构造第一行

super vs this

对比 super this
代表 父类引用 当前对象引用
调用构造 super(...) this(...)
互斥 super()this() 不能同时出现 同左

子类构造隐含 super();若父类没有无参构造,必须显式 super(...) 否则编译报错。


九、方法重写(Override)

子类重新实现父类方法,体现运行时多态。

规则 说明
方法名 + 参数 必须相同
返回值 相同或子类(协变返回)
访问权限 不能更严格(可放宽)
private/static/final 不能被重写

始终加 @Override,让编译器帮你检查拼写和签名是否正确。

重载 vs 重写

对比 重载 Overload 重写 Override
位置 同一个类 子类与父类
参数 必须不同 必须相同
返回值 无关 相同或子类
权限 无关 不能更严格
多态类型 编译时 运行时

十、多态

同一个引用类型,调用同一方法,表现不同行为。

前提:继承/实现 + 重写 + 父类引用指向子类对象

Animal a1 = new Dog();    // 向上转型(自动)
Animal a2 = new Cat();

a1.speak();  // 汪汪汪
a2.speak();  // 喵喵喵

编译看左边,运行看右边——编译检查引用类型有无该方法,运行执行实际对象的重写版本。

转型

转型 方式 安全性 说明
向上 自动 安全 只能调用父类声明的方法
向下 强制 需 instanceof 调用子类特有方法
if (a instanceof Dog) {
    Dog d = (Dog) a;
    d.bark();
}

⚠️ 成员变量没有多态——变量看左边(引用类型),方法看右边(实际对象)。

实际应用

方法参数用父类类型,兼容所有子类:

public void feed(Animal animal) { animal.speak(); }  // 一个方法搞定所有子类

十一、抽象类

abstract 修饰,不能实例化,定义通用模板,强制子类实现特定方法。

abstract class Animal {
    String name;
    public abstract void speak();        // 抽象方法,无方法体
    public void eat() { /* 普通方法 */ }  // 子类可直接用
}
特点 说明
抽象方法 子类必须实现(否则子类也是 abstract)
普通方法 子类直接继承
构造方法 ✅ 有(供子类 super 调用),但自己不能 new
成员变量 ✅ 任意

经典应用:模板方法模式

abstract class Game {
    public final void play() {     // 模板方法(final 防止子类覆盖)
        initialize();
        startPlay();
        endPlay();
    }
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();
}

十二、接口

行为规范契约,can-do 关系,支持多实现

interface Swimmable {
    void swim();                                   // 默认 public abstract
    default void rest() { System.out.println("休息"); }  // Java 8 默认方法
    static void check() { System.out.println("检查"); }  // Java 8 静态方法
}

class Duck extends Animal implements Swimmable, Flyable {  // 多实现
    @Override
    public void swim() { System.out.println("鸭子游泳"); }
    @Override
    public void fly() { System.out.println("鸭子飞"); }
}

接口成员速查

成员 默认修饰 说明
常量 public static final 必须初始化
抽象方法 public abstract 实现类必须覆写
默认方法 public default 可选覆写
静态方法 public static 接口名调用

默认方法冲突

两个接口有同名 default 方法时,实现类必须重写并指定调用哪个:

class C implements A, B {
    @Override
    public void hello() { A.super.hello(); }
}

default 方法存在的意义:向后兼容——给接口加新方法不破坏旧实现类。

抽象类 vs 接口

对比 抽象类 接口
关键字 abstract class interface
继承/实现 extends 单继承 implements 多实现
构造方法
成员变量 任意 只能常量
方法 抽象 + 普通 抽象 + default + static
设计意图 “是什么” is-a “能做什么” can-do

选择:有共同属性和部分实现 → 抽象类;只定义行为规范 → 接口;实际开发接口用得更多。


十三、SOLID 设计原则

原则 全称 一句话 典型违反
S 单一职责 SRP 一个类只做一件事 UserService 里写 sendEmail()
O 开闭原则 OCP 扩展开放,修改关闭 每加一种类型就改 if-else
L 里氏替换 LSP 子类可替换父类 Square 继承 Rectangle 改变了行为约定
I 接口隔离 ISP 接口小而专 Dog 被迫实现 fly()
D 依赖倒置 DIP 依赖抽象不依赖具体 new MySQLDatabase() 写死在 UserService 里

核心关系:开闭原则是目标,其余四条是实现手段。


十四、核心速查表

访问权限

private → 缺省 → protected → public
(从严到宽,子类重写权限只能往右走)

关键字对比

this super
当前对象 父类引用
this.变量 区分局部 super.变量 区分父类
this() 调本类构造 super() 调父类构造
构造第一行 构造第一行
互斥 互斥

转型

向上转型 向下转型
自动 强制
安全 需 instanceof
只能调父类方法 可调子类特有方法

十五、面试必背题

1. 类初始化顺序

父类静态 → 子类静态 → 父类实例代码块/构造 → 子类实例代码块/构造

2. 对象创建过程

new 分配堆内存 → 成员变量赋默认值 → 构造方法显式赋值 → 返回引用给栈

3. 多态中成员变量 vs 方法

变量:编译看左,运行也看左(无多态)
方法:编译看左,运行看右(有多态)

4. 抽象类 vs 接口选型

场景 选择
共同属性 + 部分实现 抽象类
纯行为规范,无状态 接口
需要构造方法 抽象类
需要多继承效果 接口
JDK 案例 AbstractList vs List/Comparable

5. 写了有参构造忘了无参构造 → 编译报错

6. 重写时缩小权限 → 编译报错

7. setter 不写 this → 局部变量赋值给自己,成员变量没变


十六、总览思维导图

Java 面向对象
├── 思想:封装 + 继承 + 多态
├── 类与对象:模板 vs 实例,栈引用 → 堆对象
├── 构造方法:与类同名、无返回值、自动调用、可重载
├── this:区分变量 / 调构造 / 返回自身
├── 重载 Overload:同名不同参,编译时多态
├── 封装:private + getter/setter + 校验
├── 继承:is-a、单继承、获非 private 成员
├── super:访问父类成员 / 调父类构造
├── 重写 Override:同名同参、权限不严、@Override
├── 多态:编译看左运行看右、向上/向下转型、instanceof
├── 抽象类:不可实例化、抽象方法 + 普通方法 + 构造、模板方法模式
├── 接口:can-do、多实现、default/static/private 方法、默认方法冲突
├── 抽象类 vs 接口:is-a vs can-do、有状态 vs 无状态、单继承 vs 多实现
└── SOLID:SRP / OCP / LSP / ISP / DIP

更多推荐