【面向对象三大特性(封装、继承、多态)】

面向对象三大特性(封装、继承、多态)

一、封装(Encapsulation)

概念:

将数据(属性)和对数据的操作(方法)包装在类中,对外隐藏实现细节,只暴露必要的访问接口。
核心思想:“藏”(隐藏内部细节)和**“控”**(控制外部访问)。

使用场景:
  • 保护敏感数据(如用户密码、账户余额)。

  • 防止外部直接修改对象内部状态(如年龄不能为负数)。

  • 统一数据校验逻辑(如邮箱格式验证)。

示例:
public class BankAccount {
    // 私有属性:外部无法直接访问
    private String accountNumber;//银行账号
    private double balance;//余额

    // 公开方法:控制访问和修改
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public void withdraw(double amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
        }
    }

    // 仅暴露余额查询接口
    public double getBalance() {
        return balance;
    }
}
注意事项:

使用 private 修饰符保护属性。

通过 public 的 getter/setter 方法提供可控访问。

避免过度封装(如所有属性都写 getter/setter,但无实际校验逻辑)。

二、继承(Inheritance)

1.概念:

子类继承父类的属性和方法,实现代码复用,并允许扩展新功能。
核心思想:“复用”(复用父类代码)和**“扩展”**(子类添加新特性)。

使用场景:
  • 多个类有共同属性和方法时(如动物 → 猫、狗)。

  • 需要实现多态特性时。

  • 构建分层系统(如电商系统中的用户 → 普通用户、管理员)。

示例:
// 父类:动物
class Animal {
    public void eat() {
        System.out.println("动物在吃东西");
    }
}

// 子类:狗(继承Animal)
class Dog extends Animal {
    // 扩展新方法
    public void bark() {
        System.out.println("狗在叫");
    }

    // 重写父类方法
    @Override
    public void eat() {
        System.out.println("狗在啃骨头");
    }
}
注意事项:
  • 优先使用组合(has-a)而非继承(is-a),避免过度继承导致代码耦合。
  • Java 是单继承(一个类只能继承一个父类)。
  • 子类通过 super 调用父类方法或构造器。
  • 避免“继承滥用”(如让“汽车”继承“空调”)。
2.super,以及super():

super关键字允许子类访问父类的成员,包括字段、方法和构造函数。它主要用于解决子类和父类之间的命名冲突,或者在子类中调用父类的方法或构造函数。

使用场景
Ⅰ.调用父类的构造函数‌
在子类的构造函数中,super()可以显式地调用父类的构造函数。这是初始化继承自父类的成员变量的常用方法。如果省略super()调用,则默认调用父类的无参构造函数(如果存在)。

class Parent {
    Parent() {
        System.out.println("Parent constructor called");
    }
}

class Child extends Parent {
    Child() {
        super(); // 显式调用父类的构造函数
        System.out.println("Child constructor called");
    }
}

Ⅱ.访问父类的字段
当子类和父类有同名的字段时,super可以用来访问父类的字段。

class Parent {
    int value = 10;
}

class Child extends Parent {
    int value = 20;

    void printValues() {
        System.out.println("Parent value: " + super.value); // 访问父类的字段
        System.out.println("Child value: " + this.value);   // 访问子类的字段
    }
}

Ⅲ.调用父类的方法
当子类重写了父类的方法时,super可以用来调用父类的方法。

class Parent {
    void display() {
        System.out.println("Parent display method");
    }
}

class Child extends Parent {
    @Override
    void display() {
        super.display(); // 调用父类的方法
        System.out.println("Child display method");
    }
}

Ⅳ.调用父类的构造函数和方法时的区别

  • 调用父类的构造函数必须使用super(),并且它必须是子类构造函数中的第一条语句。
  • 调用父类的方法可以使用super.methodName()语法,但也可以省略super关键字(如果方法没有被子类重写的话)。

注意事项

  • super只能在子类中使用,不能用于访问静态成员,因为静态成员属于类本身,而不是类的实例。
  • 在子类的构造函数中,super()调用必须是第一条语句(如果父类没有无参构造函数,则必须显式调用父类的某个构造函数)。
  • super不能用于访问父类的私有成员,但可以通过父类的公共方法间接访问。
  • 在使用super时,要确保父类的成员(包括字段和方法)是可见的,否则编译器会报错。

3.方法的覆盖/重写(Override):【开发应用+面试重点】
概念: 子类中定义了和父类相同的方法。
要求:

  • 子类的方法名、参数列表、返回值类型必须和父类相同
  • 子类的访问修饰符合父类相同或是比父类更宽。

使用: 子类覆盖父类中方法,则优先使用子类自身的方法。
引用名.方法名(实参);
注意:

  • 方法名、参数列表相同,返回值类型不同—》编译报错
  • 方法名、返回值类型相同,形参列表不同—》特殊的方法重载(编译和运行均通过)

场景: 当父类中的方法不足以满足子类的需求时,子类覆盖父类中的方法。

三、多态(Polymorphism)

1.概念:

同一操作作用于不同对象时,表现出不同的行为。
核心思想:“灵活”(同一接口,多种实现)。

实现方式:
  • 编译时多态(方法重载)。

  • 运行时多态(方法重写 + 父类引用指向子类对象)。

使用场景:
  • 需要统一处理不同子类对象(如绘制多种图形)。

  • 解耦代码,提高扩展性(如支付接口支持支付宝、微信支付)。

示例:

// 父类:图形
abstract class Shape {
    abstract void draw(); // 抽象方法
}

// 子类:圆形
class Circle extends Shape {
    @Override
    void draw() {
        System.out.println("绘制圆形");
    }
}

// 子类:矩形
class Rectangle extends Shape {
    @Override
    void draw() {
        System.out.println("绘制矩形");
    }
}

public class Main {
    public static void main(String[] args) {
        // 多态:父类引用指向子类对象
        Shape shape1 = new Circle();
        Shape shape2 = new Rectangle();
        
        shape1.draw(); // 输出:绘制圆形
        shape2.draw(); // 输出:绘制矩形
    }
}

注意事项:

  • 多态必须满足:继承关系 + 方法重写 + 向上转型。

  • 无法通过父类引用调用子类特有的方法(需向下转型)。

  • 使用 instanceof 避免类型转换错误。

  • 多态的核心是解耦,提高代码可扩展性。

2.instanceof关键字
instanceof关键字用于检查一个对象是否是特定类或其子类的实例,

对象 instanceof 类型

如果对象是指定类型(或其子类型)的实例,则表达式返回true;否则返回false。

示例:

/**
在这个例子中,myDog是Dog类的一个实例,同时也是Animal类的一个实例
(因为Dog继承自Animal)。因此,前两个if语句都会输出相应的消息。
第三个if语句检查myDog是否是String类的实例,
显然不是,所以也会输出相应的消息。
*/

class Animal {
    // ...
}

class Dog extends Animal {
    // ...
}

public class Test {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        
        if (myDog instanceof Dog) {
            System.out.println("myDog is an instance of Dog");
        }
        
        if (myDog instanceof Animal) {
            System.out.println("myDog is an instance of Animal");
        }
        
        if (!(myDog instanceof String)) {
            System.out.println("myDog is not an instance of String");
        }
    }
}

注意事项

  • instanceof检查的是对象的运行时类型,而不是编译时类型。
  • instanceof可以用于检查接口类型的实例,因为类可以实现接口。
  • instanceof在进行类型检查时考虑了继承关系,即如果对象是指定类型的子类的实例,那么instanceof也会返回true。
  • instanceof不能用于比较基本数据类型(如int、float等),只能用于对象类型。
  • 在使用instanceof时,要确保对象不是null,因为null不是任何类型的实例,对null使用instanceof会抛出NullPointerException。

四.总结对比表

特性	核心目标				实现方式						典型应用场景
封装	保护数据,隐藏细节	private属性 + public方法		用户类、支付系统、数据校验
继承	代码复用,扩展功能	extends关键字 + 方法重写		分类系统(动物→猫/狗)
多态	统一接口,灵活调用	方法重写 + 向上转型			图形绘制、支付方式切换

实际开发建议

  • 封装优先:所有属性默认用 private,按需开放 getter/setter。

  • 慎用继承:优先用组合(如 class Car { Engine engine; })。

  • 多态解耦:面向接口编程(如 List list = new ArrayList();)。

  • 避免过度设计:不要为了用特性而用特性,保持代码简洁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值