Java 面向对象(OOP)超详细完整版
包含:核心思想、封装、继承、多态、权限修饰符、抽象类、接口、static/final、内部类、企业真实坑点,全程按企业开发标准整理。
一、面向对象核心思想
- 一切皆对象,以对象为基本单位组织代码
- 三大特征:封装、继承、多态
- 面向过程:关注怎么做(步骤)
- 面向对象:关注谁来做(对象)
二、类与对象
1. 类
- 一类事物的模板、图纸
- 包含:属性(成员变量)+ 行为(成员方法)
2. 对象
- 类的实例
- 通过
new 类名()创建 - 存储在堆内存
3. 成员变量 vs 局部变量
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 位置 | 类内方法外 | 方法内/语句内 |
| 内存 | 堆 | 栈 |
| 生命周期 | 随对象创建/销毁 | 随方法进栈出栈 |
| 默认值 | 有默认值 | 无,必须赋值 |
| 修饰符 | 可使用权限修饰符 | 不能用权限修饰符 |
三、封装(Encapsulation)
核心思想
对外隐藏实现细节,对外提供公共访问方式
实现步骤
- 成员变量
private私有化 - 提供
getXxx()/setXxx() - 方法内做合法性校验
好处
- 安全可控
- 便于维护
- 降低耦合
- 屏蔽复杂实现
企业坑
- 过度封装:一堆无用
get/set,代码臃肿 - 不封装:直接
public变量,外部随意修改导致业务错乱 set方法不做校验,脏数据入库
四、构造方法(Constructor)
特点
- 方法名与类名完全一致
- 无返回值类型,连
void都没有 - 创建对象时
new自动调用 - 每个类默认有一个无参构造
分类
- 无参构造
- 有参构造(快速赋值)
- 全参构造(企业常用)
语法
public class User {
private String name;
// 无参
public User() {}
// 有参
public User(String name) {
this.name = name;
}
}
企业坑
- 写了有参构造,无参构造消失,导致反射/框架报错
- 构造方法内做耗时操作(查询数据库、网络请求)
- 构造方法抛异常,对象创建失败
- 循环依赖构造器,死循环
五、this 关键字
作用:
- 区分成员变量与局部变量重名
this(...)调用本类其他构造方法- 必须在第一行
- 只能调用一个
- 代表当前对象本身
六、继承(Inheritance)
语法
class 子类 extends 父类 {}
特点
- Java 是单继承,一个类只能有一个直接父类
- 可以多层继承
- 子类继承父类非私有成员(变量、方法)
方法重写(Override)
两同、两小、一大
- 方法名相同、参数列表相同
- 返回值类型 ≤ 父类
- 抛出异常 ≤ 父类
- 访问权限 ≥ 父类
super 关键字
super.xxx访问父类成员super(...)调用父类构造- 必须在构造第一行
执行顺序(面试必考)
父类静态代码块 → 子类静态代码块 → 父类代码块 → 父类构造 → 子类代码块 → 子类构造
企业坑
- 滥用继承,导致层级过深、耦合爆炸
- 父类改动,所有子类受影响(雪崩效应)
- 重写时不小心写成重载(参数改了)
- 子类构造忘记
super(),父类无无参构造时报错 - 继承导致权限泄露,破坏封装
七、多态(Polymorphism)
前提
- 继承/实现关系
- 方法重写
- 父类引用指向子类对象
Animal a = new Cat();
编译看左边,运行看右边
- 编译:能调用什么方法,看父类
- 运行:方法执行,看子类
成员变量特点
编译看左,运行也看左(变量不具备多态)
向上转型 & 向下转型
- 向上:自动转(安全)
- 向下:强制转(可能
ClassCastException) - 配合
instanceof判断
企业坑
- 强转前不判断
instanceof,直接类型转换异常 - 多态下调用成员变量结果不符合预期
- 框架大量使用多态,排查问题困难
- 静态方法多态无效(静态属于类,不属于对象)
八、权限修饰符(企业开发规范)
| 修饰符 | 同类 | 同包 | 子类 | 任意位置 |
|---|---|---|---|---|
| private | ✔ | |||
| default | ✔ | ✔ | ||
| protected | ✔ | ✔ | ✔ | |
| public | ✔ | ✔ | ✔ | ✔ |
企业规范
- 所有成员变量
private - 工具方法
private - 对外接口
public - 包内复用
default - 子类需要用
protected
九、static 关键字(静态)
修饰内容
- 静态变量(类变量)
- 静态方法
- 静态代码块
- 静态内部类
特点
- 随类加载而加载,优先于对象
- 全局只有一份
- 静态方法不能访问非静态成员
- 静态方法不能用
this/super
静态代码块
static {
// 类加载时执行,只执行一次
}
企业坑
- 静态变量线程不安全,高并发下数据错乱
- 静态方法无法被 Spring AOP、事务管理
- 静态持有大对象,导致内存泄漏
- 滥用静态,代码难以测试、难以扩展
十、final 关键字
作用
- 修饰类:类不能被继承
- 修饰方法:方法不能被重写
- 修饰变量:变量变为常量,只能赋值一次
常量规范
public static final XXX 全大写,下划线分隔
企业坑
final修饰引用类型,对象内容仍可修改- 接口变量默认
public static final - 过度使用
final导致代码僵化
十一、代码块
- 局部代码块:方法内,限制变量作用域
- 构造代码块:类内方法外,每次创建对象执行
- 静态代码块:类加载执行一次
- 同步代码块:线程安全
十二、抽象类(abstract)
语法
abstract class Animal {
// 抽象方法:无方法体
public abstract void eat();
}
规则
- 抽象类不能实例化
- 包含抽象方法的类必须是抽象类
- 抽象类可以有普通方法、变量、构造器
- 子类必须重写所有抽象方法,否则子类也要抽象
使用场景
模板设计模式,定义规范 + 提供通用逻辑
十三、接口(Interface)
JDK7 及以前
- 常量:
public static final - 抽象方法:
public abstract
JDK8+
- 允许默认方法
default - 允许静态方法
- 更像一个能力扩展
implements
class Cat implements Run, Jump {}
接口 vs 抽象类
- 接口:多实现,侧重能力
- 抽象类:单继承,侧重模板
企业坑
- JDK8 接口默认方法冲突,编译报错
- 一个类实现多个接口,方法签名冲突
- 接口常量修改,所有实现类需重新编译
十四、内部类
分类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类(企业最常用)
匿名内部类
简化创建实现类/子类对象:
new Thread(new Runnable() {
@Override
public void run() {}
}).start();
企业坑
- 匿名内部类持有外部类引用,容易内存泄漏
- 大量匿名类导致类文件过多
- Lambda 出现后基本替代匿名内部类
十五、企业面向对象开发规范
- 单一职责:一个类只做一件事
- 少用继承,多用组合/接口
- 面向接口编程,而非面向实现
- 禁止超大类、万能类
- 属性私有,对外提供安全访问
- 禁止随意使用 static
- 方法粒度细化,便于复用与测试
十六、本章高频面试题
- 重载与重写的区别
- 多态的前提与执行特点
- this 和 super 区别
- 接口和抽象类区别
- static 应用场景与内存
- 权限修饰符使用场景
- 代码块执行顺序
- 为什么 Java 单继承