Java面向对象基础总结
Java 面向对象基础总结
作者:没有四次元口袋的蓝胖
日期:2026-06-05
标签:Java, 面向对象
一、面向对象思想
核心理念
用"对象"来描述和解决问题:谁来做、做什么,而非怎么一步步做。
思维四步法
- 找对象(名词 → 类)→ 2. 定属性(形容词 → 成员变量)→ 3. 定行为(动词 → 方法)→ 4. 建关系(继承/组合/调用)
三大特征
| 特征 | 一句话 | 比喻 |
|---|---|---|
| 封装 | 隐藏细节,暴露接口 | 自动挡汽车——踩油门就行 |
| 继承 | 子类复用父类能力 | 儿子继承爸爸的姓和房子 |
| 多态 | 同一指令,不同表现 | “叫一声”——猫喵、狗汪 |
二、类与对象
类 = 模板,对象 = 实例(设计图纸 vs 造出来的车)
public class Student {
String name; // 属性
int age;
public void study() { System.out.println(name + "正在学习"); } // 行为
}
内存模型
- 栈:存放引用(
stu1、stu2) - 堆:存放对象实例(属性值 + 方法引用)
- 引用赋值
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
更多推荐
所有评论(0)