Java 面向对象
三大特性 + 抽象 vs 接口
这一节我们彻底搞懂 Java 的"对象思维"——为什么要有"类"和"对象"?封装、继承、多态到底在解决什么问题?
学 OOP 的关键:不要死记"三个特性是什么",而要理解为什么需要它们。每讲一个特性,我会先告诉你"它解决了什么痛点"。
1
为什么需要"面向对象"?
💡 动机:把数据 + 操作数据的方法绑在一起
在写 Java 程序之前,先理解 OOP 解决了什么问题。
🏫 现实例子:管理一个学校的学生
❌ 不用 OOP(散装数据)
每个学生是一堆散装变量:
→ 数据乱、容易错、扩展难
每个学生是一堆散装变量:
name1, age1, score1name2, age2, score2→ 数据乱、容易错、扩展难
→
✅ 用 OOP(学生 = 一个对象)
把"学生"定义成一个类:
每个具体学生是这个类的对象:
把"学生"定义成一个类:
class Student { ... }每个具体学生是这个类的对象:
Student s = new Student(...)
01
封装
Encapsulation
把数据藏起来,只暴露必要的方法。外部不能乱改。
🎁 像一个上锁的盒子
02
继承
Inheritance
子类复用父类代码,不用从零写。子类还能扩展新能力。
👨👩👧 孩子继承父母的特征
03
多态 ⭐
Polymorphism
同一句代码,根据对象实际类型,表现出不同行为。
🔌 USB 接口,插啥是啥
2
类和对象:先搞懂这个
💡 类 = 模板,对象 = 模板做出来的东西
在讲三大特性之前,必须先理解 Java 里"类"和"对象"的关系。
// 类(Class)= 模板/图纸,定义一类事物长啥样、能干啥
public class Student {
String name;
int age;
public void introduce() {
System.out.println("我叫 " + name + ",今年 " + age + " 岁");
}
}
// 对象(Object)= 根据类创建的具体实例
public class Main {
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "张三";
s1.age = 20;
s1.introduce();
Student s2 = new Student();
s2.name = "李四";
s2.age = 22;
s2.introduce();
}
}
记住这个比喻:类是手机设计图,对象是流水线上的真手机。一张图纸可以做 N 部手机。
3
封装:把数据藏起来
💡 动机:防止外部乱改数据,统一管理操作
如果不封装,别人可以随便改:s1.age = -100,明显不合理。
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public void setAge(int age) {
if (age < 0 || age > 150) {
System.out.println("年龄不合法!");
return;
}
this.age = age;
}
}
| 修饰符 | 本类 | 同包 | 子类 | 其他类 |
|---|---|---|---|---|
| private | ✓ | ✗ | ✗ | ✗ |
| default | ✓ | ✓ | ✗ | ✗ |
| protected | ✓ | ✓ | ✓ | ✗ |
| public | ✓ | ✓ | ✓ | ✓ |
4
继承:子类复用父类
💡 动机:避免重复代码,把公共部分抽出来
假如有 Dog、Cat、Bird,它们都有 name 字段和 eat() 方法。重复写太蠢,抽出 Animal 父类。
public class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " 在吃东西");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void eat() {
super.eat();
System.out.println(name + " 吃得很快");
}
public void bark() {
System.out.println("汪汪!");
}
}
继承层级:子类继承父类所有 public/protected 成员
Animal
父类
父类
Dog
extends Animal
extends Animal
Cat
extends Animal
extends Animal
关键规则:Java 里一个类只能继承一个父类(单继承)。想要"多继承"效果?用接口。
5
多态:同一句代码,不同表现 ⭐
💡 动机:写出能处理"任何子类"的通用代码
假设你有一个方法要喂一群动物,动物有狗有猫各叫各的。多态让你写一个方法喂所有动物。
// 多态写法:父类引用 a 可以指向任何子类对象
Animal a = new Dog("旺财");
a.eat(); // 执行的是 Dog 的 eat(),不是 Animal 的!
// 这就是多态的威力:写一个方法处理所有 Animal
public static void feed(Animal a) {
System.out.print("主人喂食 → ");
a.eat(); // 自动根据 a 实际类型调用对应的 eat
}
feed(new Dog("旺财")); // → Dog 的 eat
feed(new Cat("小花")); // → Cat 的 eat
点下面的按钮,看实际执行结果:
// 选上面任意一个,看实际执行
Animal a = new Dog("旺财");
a.eat(); // 多态:实际调用 Dog.eat()
// 输出 ↓
→ 点按钮看输出
6
抽象类 vs 接口 ⭐ 面试必问
💡 动机:定义"规范"——"子类必须实现这些方法"
有时候父类不知道具体怎么实现某个方法(比如 Animal 的 sound(),不同动物叫声不一样),就让父类只声明不实现。
// 抽象类:用 abstract 关键字修饰
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void sleep() {
System.out.println(name + " 睡觉中");
}
public abstract void sound(); // 抽象方法:没方法体
}
class Cat extends Animal {
public Cat(String name) { super(name); }
@Override
public void sound() {
System.out.println("喵~");
}
}
// 接口:用 interface 关键字
public interface Swimmable {
void swim(); // 默认 public abstract
default void dive() { // Java 8+ 可以有默认方法
System.out.println("潜水!");
}
}
// 一个类可以实现多个接口
class Duck implements Swimmable, Flyable {
@Override
public void swim() {
System.out.println("鸭子在游泳");
}
}
| 对比项 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract class | interface |
| 继承方式 | extends,单继承 | implements,可多实现 |
| 字段 | 可以有普通字段 | 只能 public static final |
| 方法 | 抽象 + 具体方法都可以 | Java 8 前只能抽象;之后可有 default/static 方法 |
| 构造器 | ✅ 可以有 | ❌ 不能有 |
| 使用场景 | 子类和父类本质相同 | 给类添加能力 |
小白记法:
• 抽象类 = "我们都是一家人(都是动物)" → 用
• 接口 = "我会新技能(会飞)" → 用
• 抽象类 = "我们都是一家人(都是动物)" → 用
extends• 接口 = "我会新技能(会飞)" → 用
implements
你的作业(分步走)
- 写一个
Dog类:name字段(private),构造器,getName,bark()方法打印"汪汪!" - 加继承:写一个
Animal父类(有name和eat()),让Dog继承它。在 Dog 里@Override eat() - 体验多态:写一个方法
feed(Animal a),调用a.eat() - 玩接口:写一个
Swimmable接口(有swim()方法),让Duck类实现它 - 把代码贴给我,我帮你 review