Java是纯面向对象编程语言,面向对象(OOP)是Java的核心基石,也是后端面试、业务开发、框架底层的核心考点。所有Java代码、Spring框架、工程设计模式全部基于OOP思想实现。
本文全覆盖核心知识点:类与对象、三大特性(封装/继承/多态)、抽象类、接口、各类内部类,搭配完整可运行案例、底层原理、工程最佳实践、高频坑点、面试标准答案,零基础可看懂、面试可直接背诵、项目可直接落地。
一、面向对象思想概述
1.1 面向过程 vs 面向对象
-
面向过程:关注步骤、流程,以函数为核心,适合简单小项目,代码复用性、扩展性极差(代表语言:C语言)
-
面向对象:关注事物、实体,以类和对象为核心,封装属性和行为,具备高复用、高扩展、低耦合特性(代表语言:Java)
OOP核心设计思想:万物皆对象,通过封装、继承、多态实现代码复用与业务解耦。
二、类与对象(OOP基础)
2.1 核心定义
-
类(Class):是对象的模板、抽象概念,定义对象的属性(成员变量)和行为(成员方法)
-
对象(Object):是类的实例、具体实体,根据类模板创建的真实个体
通俗理解:类是图纸,对象是图纸造出来的产品,一张图纸可以造出无数个产品。
2.2 类的组成结构
标准Java类包含四大核心部分:
-
成员变量(属性):描述对象的特征(姓名、年龄、性别)
-
成员方法(行为):描述对象的功能(吃饭、学习、工作)
-
构造方法:创建对象时初始化属性,与类名同名,无返回值
-
代码块/内部类:拓展结构,用于初始化、功能拓展
2.3 完整实战代码(类与对象)
// 定义人类(模板/类)
public class Person {
// 成员变量(属性)
private String name;
private int age;
// 无参构造方法
public Person() {}
// 有参构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 成员方法(行为)
public void study() {
System.out.println(name + "正在学习,年龄:" + age);
}
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
// 测试类
class Test {
public static void main(String[] args) {
// 通过类创建对象(实例化)
Person p1 = new Person("张三", 20);
Person p2 = new Person("李四", 22);
// 对象调用方法
p1.study();
p2.study();
}
}
2.4 成员变量 vs 局部变量(面试高频)
| 对比维度 | 成员变量 | 局部变量 |
|---|---|---|
| 定义位置 | 类中、方法外 | 方法内、代码块内 |
| 默认值 | 有默认值(int=0、String=null) | 无默认值,必须手动初始化 |
| 生命周期 | 随对象创建而存在,对象销毁才消失 | 方法调用时创建,方法结束立即销毁 |
| 修饰符 | 可使用private/public/static等修饰 | 只能用final修饰 |
三、面向对象三大特性
3.1 封装(Encapsulation)—— 安全性
封装核心定义:将类的属性私有化,对外提供公开的get/set方法访问属性,隐藏内部实现细节,仅暴露访问入口。
3.1.1 封装核心作用
-
保护数据安全,防止外部随意篡改属性
-
统一数据校验入口,在set方法中做参数校验
-
降低代码耦合,内部逻辑修改不影响外部调用
3.1.2 封装进阶实战(带数据校验)
public class Student {
// 私有属性,外部无法直接访问
private int age;
// 对外提供set方法,统一校验数据
public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
} else {
System.out.println("年龄不合法!");
}
}
public int getAge() {
return age;
}
}
3.2 继承(Inheritance)—— 复用性
继承核心定义:子类(派生类)继承父类(超类)的属性和方法,实现代码复用、功能拓展,使用 extends 关键字。
3.2.1 继承核心特点
-
Java 单继承:一个子类只能有一个直接父类,一个父类可以有多个子类
-
继承父类非私有属性和方法,private资源无法继承
-
子类可以拓展新方法,也可以重写父类方法
-
所有类默认直接/间接继承
Object类(顶层父类)
3.2.2 继承实战代码
// 父类:动物类
class Animal {
public void eat() {
System.out.println("动物需要进食");
}
}
// 子类:狗类,继承动物类
class Dog extends Animal {
// 子类拓展独有方法
public void bark() {
System.out.println("狗狗汪汪叫");
}
}
// 测试
class TestExtends {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 继承父类方法
dog.bark(); // 子类自有方法
}
}
3.2.3 super关键字用法
-
super\(\):调用父类构造方法,必须放在子类构造第一行 -
super\.属性:访问父类成员变量 -
super\.方法\(\):调用父类成员方法
3.3 多态(Polymorphism)—— 扩展性
多态核心定义:同一行为,不同子类有不同实现,父类引用指向子类对象,是OOP最核心、框架底层最常用的特性。
3.3.1 多态实现三大条件(面试必考)
-
必须存在继承/实现关系
-
必须存在方法重写(Override)
-
必须存在父类引用指向子类对象(向上转型)
3.3.2 多态实战代码
// 父类
class Animal {
public void run() {
System.out.println("动物奔跑");
}
}
// 子类1
class Cat extends Animal {
@Override
public void run() {
System.out.println("猫咪轻盈奔跑");
}
}
// 子类2
class Tiger extends Animal {
@Override
public void run() {
System.out.println("老虎极速奔跑");
}
}
// 多态测试
class TestPoly {
public static void main(String[] args) {
// 父类引用指向子类对象,实现多态
Animal a1 = new Cat();
Animal a2 = new Tiger();
a1.run(); // 执行子类重写方法:猫咪轻盈奔跑
a2.run(); // 执行子类重写方法:老虎极速奔跑
}
}
3.3.3 向上转型 & 向下转型
-
向上转型(自动):子类转父类,多态核心,丢失子类独有方法
-
向下转型(强制):父类转子类,用于恢复子类独有方法,需强转,存在转型异常风险
3.3.4 重写(Override) vs 重载(Overload) 核心区别
-
重写:子类覆盖父类方法,方法名、参数、返回值完全一致,运行时多态
-
重载:同一个类中,方法名相同、参数列表不同,与继承无关,编译时多态
四、抽象类 & 接口(面试重中之重)
4.1 抽象类(abstract class)
被 abstract 修饰的类为抽象类,用于抽取通用模板,约束子类行为,不能实例化。
4.1.1 核心特性
-
抽象类可以包含普通方法、抽象方法、成员变量、构造方法
-
抽象方法:无方法体,必须被子类重写实现
-
抽象类不能被new实例化,只能被继承
-
子类继承抽象类,必须实现所有抽象方法,否则子类也必须是抽象类
4.1.2 抽象类实战
// 抽象父类
abstract class Shape {
// 抽象方法:无实现,约束子类必须实现
public abstract void getArea();
// 普通方法
public void printInfo() {
System.out.println("这是一个图形");
}
}
// 子类实现抽象类
class Circle extends Shape {
@Override
public void getArea() {
System.out.println("圆形面积计算");
}
}
4.2 接口(interface)
接口是行为规范、能力标准,是方法的集合,用于定义规则、解耦代码,使用 implements 实现。
4.2.1 核心特性
-
JDK8前:接口只能有全局常量、抽象方法
-
JDK8:新增默认方法(default)、静态方法(static)
-
JDK9:新增私有方法(private)
-
接口无构造方法、不能实例化
-
Java多实现:一个类可以实现多个接口,解决单继承局限
4.2.2 接口实战
// 定义行为接口
interface Runable {
// 抽象方法(默认public abstract)
void run();
// JDK8默认方法
default void sleep() {
System.out.println("生物需要休息");
}
}
// 实现类
class Rabbit implements Runable {
@Override
public void run() {
System.out.println("兔子快速奔跑");
}
}
4.3 抽象类 vs 接口(终极面试对比)
| 对比维度 | 抽象类 | 接口 |
|---|---|---|
| 核心定位 | 模板复用,描述事物本质 | 行为规范,描述额外能力 |
| 继承/实现 | 单继承 extends | 多实现 implements |
| 成员变量 | 普通变量、常量都支持 | 只能是全局常量(public static final) |
| 构造方法 | 有构造方法 | 无构造方法 |
| 使用场景 | 抽取公共代码、复用模板 | 定义规则、解耦、拓展能力 |
五、内部类详解(分类+实战)
内部类:定义在类内部的类,可以访问外部类所有资源(包括私有),用于封装局部专属功能、减少类文件数量。分为四种:成员内部类、静态内部类、局部内部类、匿名内部类。
5.1 成员内部类(普通内部类)
定义在类中、方法外,属于外部类的成员,依附外部类实例存在。
public class Outer {
private String msg = "外部类私有数据";
// 成员内部类
class Inner {
public void show() {
// 可直接访问外部类私有属性
System.out.println(msg);
}
}
// 测试
public static void main(String[] args) {
// 成员内部类创建方式
Outer.Inner inner = new Outer().new Inner();
inner.show();
}
}
特点:不能定义静态资源、依赖外部类对象、可访问外部类所有私有资源。
5.2 静态内部类(static 内部类)
被static修饰的内部类,属于外部类本身,不依赖外部类实例。
public class OuterStatic {
private static String info = "静态数据";
// 静态内部类
static class Inner {
public void print() {
System.out.println(info);
}
}
public static void main(String[] args) {
// 直接通过外部类.内部类创建
OuterStatic.Inner inner = new OuterStatic.Inner();
inner.print();
}
}
工程场景:工具类、实体嵌套、单例模式,是开发最常用的内部类。
5.3 局部内部类
定义在方法、代码块内部的类,仅当前方法内有效,作用域极小。
public class LocalInner {
public void test() {
// 局部内部类
class Inner {
public void hello() {
System.out.println("局部内部类方法");
}
}
// 仅当前方法可使用
new Inner().hello();
}
}
5.4 匿名内部类(极简高频)
无类名的局部内部类,快速实现接口/继承抽象类,简化代码,线程、回调场景高频使用。
interface Hello {
void sayHello();
}
public class AnonymousInner {
public static void main(String[] args) {
// 匿名内部类快速实现接口
Hello hello = new Hello() {
@Override
public void sayHello() {
System.out.println("匿名内部类实现");
}
};
hello.sayHello();
}
}
JDK8后可被Lambda表达式替代,简化冗余代码。
六、全文核心总结(面试必背)
-
类与对象:类是抽象模板,对象是具体实例,万物皆对象,构造方法用于对象初始化
-
封装:私有化属性、公开方法,隐藏细节、保护数据、统一校验入口
-
继承:extends实现单继承,复用父类代码,super访问父类资源,支持方法重写
-
多态:继承+重写+向上转型,同一行为不同实现,提升代码扩展性
-
抽象类:模板抽象,可包含普通方法和抽象方法,单继承,用于代码复用
-
接口:行为规范,多实现,解耦拓展,JDK8+支持默认/静态方法
-
内部类:分四种类型,静态内部类工程最常用,匿名内部类快速实现接口回调
七、高频面试简答题
-
面向对象三大特性及作用? 封装(安全)、继承(复用)、多态(扩展),是Java代码高复用、低耦合、易维护的核心。
-
重写和重载的区别? 重写基于继承、方法签名完全一致、运行时多态;重载同类内、参数不同、编译时多态。
-
抽象类可以有构造方法吗? 可以,用于子类初始化父类资源,自身不能实例化。
-
接口和抽象类如何选择? 需要代码复用、通用模板用抽象类;需要定义规范、多拓展、解耦用接口。
-
**静态内部类和普通内部类区别?**静态内部类不依赖外部类实例,可定义静态资源;普通内部类依赖外部对象,无静态资源。
-
Java为什么不支持多继承? 避免父类方法冲突、二义性问题,通过接口多实现替代多继承。
-
多态的实现原理? 基于动态绑定,编译看父类,运行看子类,执行子类重写后的方法。