JavaSE-面向对象三大特性:封装、继承、多态详解
·
一、封装
1. 为什么要有封装?
问题示例:
public class PrivateTest {
public static void main(String[] args) {
Animal animal = new Animal();
animal.legs = -3; // 不合理的赋值
animal.move(); // 输出:动物用 -3 条腿走路...
}
}
class Animal {
int legs; // 属性直接暴露,可被任意修改
public void move() {
System.out.println("动物用" + legs + "条腿走路...");
}
}
封装的目的:
-
将对象的属性和实现细节隐藏,只对外提供公共的访问方式
-
提高代码的安全性:防止属性被随意修改
-
提高代码的维护性:内部实现修改不影响外部调用
-
原则:该隐藏的隐藏,该暴露的暴露
2. 访问修饰符
|
修饰符 |
同类 |
同包 |
子类 |
不同包 |
说明 |
|---|---|---|---|---|---|
|
public |
✓ |
✓ |
✓ |
✓ |
公共访问 |
|
protected |
✓ |
✓ |
✓ |
受保护访问 |
|
|
默认 |
✓ |
✓ |
包内访问 |
||
|
private |
✓ |
类内访问 |
3. 属性封装示例
class Animal {
// 隐藏属性:private修饰
private int legs;
private String name;
// 暴露公共的setter方法,控制属性的赋值
public void setLegs(int legs) {
if (legs == 2 || legs == 4) { // 数据校验
this.legs = legs;
} else {
System.out.println("腿的数量不合法!");
}
}
// 暴露公共的getter方法
public int getLegs() {
return legs;
}
}
4. 方法封装示例
class Car {
private int speed;
// 隐藏内部实现细节
private void changeMeter() {
// 更新码表显示
}
private void changeSpeed(int delta) {
this.speed += delta;
}
// 暴露公共接口
public void changeGear(int gear) {
changeMeter(); // 内部调用
changeSpeed(gear * 10); // 内部调用
System.out.println("当前速度:" + speed);
}
}
二、继承
1. 为什么需要继承?
场景分析:
人(父类)
↙ ↓ ↘
学生 老师 工人
-
学生、老师、工人都有人的基本属性和行为
-
每个子类又有自己特有的属性和方法
-
继承可避免代码冗余,提高复用性
2. 继承语法
// 父类
class Person {
String name;
int age;
String gender;
public void eat() {
System.out.println("吃饭");
}
}
// 子类继承父类
class Student extends Person {
String studentId;
public void study() {
System.out.println("学习");
}
}
3. 方法重写(Override)
class Animal {
public void move() {
System.out.println("动物移动");
}
}
class Dog extends Animal {
// 重写父类方法
@Override
public void move() {
System.out.println("狗用四条腿跑");
}
}
4. 重写 vs 重载
|
区别点 |
重写(Override) |
重载(Overload) |
|---|---|---|
|
范围 |
子类继承父类 |
同一个类内部 |
|
场景 |
业务延伸,方法改进 |
同一个功能,参数不同 |
|
语法 |
同名、同参数、同返回类型 |
同名、不同参数列表 |
|
访问权限 |
不能更严格(可更宽松) |
无限制 |
5. super关键字
class Father {
int age = 40;
public Father() {
System.out.println("父类构造方法");
}
public void show() {
System.out.println("父类方法");
}
}
class Son extends Father {
int age = 20;
public Son() {
super(); // 调用父类构造方法(可省略)
}
public void display() {
System.out.println("子类年龄:" + age);
System.out.println("父类年龄:" + super.age); // 访问父类属性
super.show(); // 调用父类方法
}
}
6. final关键字
final的作用:
-
修饰类:不能被继承(如String类)
-
修饰方法:不能被重写
-
修饰变量:变为常量,不可修改
// final修饰类
final class FinalClass {
// 不能被继承
}
// final修饰方法
class Base {
public final void finalMethod() {
// 不能被子类重写
}
}
// final修饰变量
class Circle {
public final double PI = 3.14159; // 常量
// PI = 3.15; // 错误!不能修改
}
三、多态
1. 为什么要有多态?
问题代码:
class ZooKeeper {
// 需要为每种动物写一个feed方法
public void feed(Dog dog) {
dog.eat();
}
public void feed(Cat cat) {
cat.eat();
}
public void feed(Lion lion) {
lion.eat();
}
// ... 需要无数个重载方法
}
多态解决方案:
class ZooKeeper {
// 一个方法搞定所有动物
public void feed(Animal animal) {
animal.eat(); // 运行时根据实际对象类型调用对应方法
}
}
2. 什么是多态?
多态定义: 父类引用指向子类对象
语法:
父类类型 对象名 = new 子类类型();
示例:
// 父类引用指向子类对象
Animal animal1 = new Dog(); // 多态
Animal animal2 = new Cat(); // 多态
// 只能调用父类中声明的方法
// 实际执行的是子类重写的方法
animal1.eat(); // 执行Dog的eat方法
animal2.eat(); // 执行Cat的eat方法
3. instanceof运算符
public void showAnimal(Animal animal) {
animal.eat();
// 类型判断
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 向下转型
dog.watchHouse(); // 调用Dog特有方法
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal; // 向下转型
cat.catchMouse(); // 调用Cat特有方法
}
}
总结
|
特性 |
核心思想 |
主要作用 |
实现方式 |
|---|---|---|---|
|
封装 |
隐藏细节,暴露接口 |
提高安全性、可维护性 |
private、getter/setter |
|
继承 |
代码复用,扩展功能 |
避免重复代码,实现层次结构 |
extends、super |
|
多态 |
统一接口,不同实现 |
提高扩展性,降低耦合 |
父类引用、方法重写 |
掌握面向对象这三大特性,是Java编程的基础,也是写出高质量代码的关键。在实际开发中,要灵活运用这些特性,设计出高内聚、低耦合的程序结构。
更多推荐

所有评论(0)