封装
核心思想
封装是指将数据(属性)和操作数据的方法(行为)捆绑到一个单元(即类)中,并对外部隐藏对象的内部实现细节,只暴露有限的、受控制的接口与外界进行交互,就像一个黑盒子,你知道怎么用(输入什么,得到什么),但不知道它内部是如何工作的。

目的与好处
- 数据隐藏和保护:防止外部代码随意访问和修改对象的内部状态,避免了数据被意外破坏或非法篡改。
- 提高安全性:通过访问控制修饰符(如
private)来保护核心数据,只允许通过公共方法(public的getter和setter)进行访问和修改,可以在这些方法中加入校验逻辑。 - 简化接口:使用者只需要关心如何通过公共接口与对象交互,而不必关心其复杂的内部实现,降低了使用复杂度。
- 提高可维护性:当内部逻辑需要修改时,只要不改变公共接口,就不会影响到调用该代码的其他部分,使得代码更容易维护和升级。
实现方式
在Java中,主要通过以下方式实现封装:
- 使用
private关键字:将类的属性(成员变量)声明为private,使其只能在类的内部被访问。 - 提供
public的访问器(Getter)和修改器(Setter)方法:为每个private属性提供public的getXxx()和setXxx()方法,用于获取和设置属性值。
代码示例
// 1. 定义一个封装的类
public class Student {
// 2. 使用 private 修饰属性,将其隐藏起来
private String name;
private int age;
private String gender;
// 3. 提供 public 的构造方法,用于创建对象时初始化数据
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
// 4. 提供 public 的 Getter 方法,用于获取私有属性的值
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getGender() {
return gender;
}
// 5. 提供 public 的 Setter 方法,用于修改私有属性的值,并可以加入校验逻辑
public void setAge(int newAge) {
// 可以在这里添加校验逻辑,比如年龄不能为负数
if (newAge > 0) {
this.age = newAge;
} else {
System.out.println("年龄不能为负数!");
}
}
// 可以不提供对某些属性的修改方法,实现“只读”
// public void setName(String name) { ... }
}
// 6. 使用封装后的类
public class Main {
public static void main(String[] args) {
Student student = new Student("张三", 20, "男");
// 正确访问方式:通过公共方法
System.out.println("学生姓名: " + student.getName()); // 输出: 学生姓名: 张三
System.out.println("学生年龄: " + student.getAge()); // 输出: 学生年龄: 20
// 错误访问方式:直接访问私有属性(编译会报错)
// student.name = "李四"; // The field Student.name is not visible
// 通过 Setter 方法修改年龄,并触发校验逻辑
student.setAge(21); // 正常修改
System.out.println("修改后的年龄: " + student.getAge()); // 输出: 修改后的年龄: 21
student.setAge(-5); // 触发校验逻辑,输出: 年龄不能为负数!
System.out.println("年龄未改变: " + student.getAge()); // 输出: 年龄未改变: 21
}
}
继承
核心思想
继承是面向对象编程中实现代码重用和建立类之间层次关系的重要机制,它允许一个类(称为子类 或 派生类)获取另一个类(称为父类 或 基类)的属性和方法,子类不仅继承了父类的非私有成员,还可以在此基础上扩展新的功能或重写(覆盖)父类的方法。
目的与好处
- 代码重用:将公共的属性和方法定义在父类中,子类可以直接继承,无需重复编写,提高了代码复用性。
- 建立类层次结构:通过继承,可以清晰地表示“是一个”(is-a)的关系,狗”是一个“动物”,“经理”是一个“员工”。
- 便于扩展:可以在子类中添加新的属性和方法,或者修改父类的行为(通过方法重写),使得程序结构更加灵活和可扩展。
实现方式
在Java中,使用 extends 关键字来实现继承。
- 语法:
class Subclass extends Superclass { ... } - 特点:
- Java只支持单继承,即一个类只能有一个直接父类,但可以通过接口实现多重继承的效果。
- 子类会继承父类的
public和protected成员,但不会继承父类的private成员(尽管它们存在)。 - 子类会继承父类的构造方法吗?不会,子类在创建对象时,会默认调用父类的无参构造方法(通过
super()),如果父类没有无参构造方法,则子类必须显式调用父类的其他构造方法。
代码示例
// 1. 父类
public class Animal {
private String name; // 私有成员,子类无法直接访问
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西。");
}
public void sleep() {
System.out.println(name + "正在睡觉。");
}
}
// 2. 子类,继承自 Animal
public class Dog extends Animal {
// Dog 类自动继承了 Animal 的非私有成员(如 name, eat(), sleep())
// Dog 可以拥有自己的新成员
private String breed;
// 3. 子类的构造方法
public Dog(String name, String breed) {
// 必须通过 super() 调用父类的构造方法来初始化继承的属性
super(name);
this.breed = breed;
}
// 4. Dog 类特有的方法
public void bark() {
System.out.println(getName() + "在汪汪叫!"); // 需要通过公共方法访问父类私有属性
}
// 5. 重写父类的方法
@Override
public void eat() {
System.out.println(getName() + "正在吃狗粮。");
}
}
// 6. 使用继承
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("旺财", "中华田园犬");
// 调用从父类继承的方法
myDog.eat(); // 输出: 旺财正在吃狗粮。(调用的是重写后的方法)
myDog.sleep(); // 输出: 旺财正在睡觉。(调用的是继承来的方法)
// 调用子类自己的方法
myDog.bark(); // 输出: 旺财在汪汪叫!
}
}
多态
核心思想
多态的字面意思是“多种形态”,在Java中,多态指的是同一个接口,使用不同的实例而执行不同操作,就是允许将子类类型的对象赋值给父类类型的引用,通过这个父类引用来调用方法时,实际执行的是子类重写后的方法。

目的与好处
- 提高灵活性:允许编写更通用、更灵活的代码,一个方法可以接受父类类型的参数,那么任何子类的对象都可以传入,而不需要为每个子类都写一个方法。
- 提高可扩展性:当需要增加新的子类时,只要它继承了父类并重写了相应的方法,原有的使用父类引用的代码无需修改即可正确工作,符合“开闭原则”(对扩展开放,对修改关闭)。
- 简化代码:减少了代码的重复和条件判断(如
if-else或switch),使代码更优雅、更易于维护。
实现方式
多态的实现需要具备三个必要条件:
- 继承:必须有类之间的继承关系。
- 方法重写:子类必须重写父类的方法。
- 父类引用指向子类对象:
Parent p = new Child();
代码示例
// 1. 父类
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 2. 子类1
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪");
}
}
// 3. 子类2
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵");
}
}
// 4. 一个使用多态的方法
public class AnimalSoundMaker {
// 这个方法可以接受任何 Animal 类型的对象
public void letAnimalSound(Animal animal) {
animal.makeSound(); // 这里会发生多态
}
}
// 5. 测试多态
public class Main {
public static void main(String[] args) {
AnimalSoundMaker maker = new AnimalSoundMaker();
// 创建子类对象,但用父类引用指向它
Animal myDog = new Dog();
Animal myCat = new Cat();
// 调用同一个方法,但执行了不同的行为
maker.letAnimalSound(myDog); // 输出: 汪汪
maker.letAnimalSound(myCat); // 输出: 喵喵
}
}
在这个例子中,letAnimalSound 方法只关心 Animal 这个类型,不关心具体是 Dog 还是 Cat,当传入 Dog 对象时,animal.makeSound() 实际调用的是 Dog 类的 makeSound() 方法;当传入 Cat 对象时,实际调用的是 Cat 类的 makeSound() 方法,这就是多态的体现。
| 特征 | 核心思想 | 关键字/实现方式 | 主要目的 |
|---|---|---|---|
| 封装 | 数据与方法的捆绑,隐藏内部细节,只暴露接口 | private, public 的 getter/setter |
保护数据、提高安全性、简化接口、便于维护 |
| 继承 | 子类获取父类的属性和方法,建立“is-a”关系 | extends |
代码重用、建立层次结构、便于扩展 |
| 多态 | 同一接口,不同实例执行不同操作 | 继承、方法重写、父类引用指向子类对象 | 提高灵活性、可扩展性,简化代码 |
这三个特征相辅相成,共同构成了Java面向对象编程的强大框架,使得Java程序结构清晰、易于维护和扩展。

