当前位置: 首页 > news >正文

Java—封装、继承与多态

面向对象编程的三个基本特征—封装、继承、多态。

一、封装

封装的核心思想是将数据(属性)和操作数据的方法(行为)绑定在一起,并对外隐藏内部实现细节,仅通过受控的接口与外界交互,提高代码的可维护性和安全性。

1.1 封装的目的

  • 保护数据完整性:防止外部代码直接修改对象内部数据。

  • 隐藏实现细节:类的内部逻辑可以自由修改,不影响外部调用者。

  • 提高代码安全性:通过受控的访问权限,避免非法操作。

  • 降低耦合性:外部代码依赖接口而非具体实现。

1.2 封装的实现

  1. 将属性设为private:禁止外部直接访问属性。

  2. 提供公共方法(Getter/Setter):通过方法间接读写属性,可添加逻辑控制。

  3. 构造方法初始化:确保对象创建时数据合法。

1.3 示例代码

public class test {// 私有属性,外部无法直接访问private String name;private int age;// 构造方法:初始化对象时验证数据合法性public test(String name, int age) {setName(name);setAge(age);}// Getter方法:提供对属性的受控访问public String getName() {return name;}// Setter方法:在赋值时添加验证逻辑public void setName(String name) {if (name == null || name.trim().isEmpty()) {throw new IllegalArgumentException("姓名不能为空");}this.name = name;}public int getAge() {return age;}public void setAge(int age) {if (age < 0 || age > 150) {throw new IllegalArgumentException("年龄无效");}this.age = age;}}

1.4 封装的优点

  • 数据验证:在setAge方法中可检查年龄是否合法。

  • 灵活性:后续可修改内部实现,不影响外部调用。

  • 安全性:外部无法绕过验证逻辑直接修改属性。

二、继承

Java 继承(Inheritance) 是面向对象编程的另一个核心特性,它允许一个类(子类/派生类)基于另一个类(父类/基类)构建,继承父类的属性和方法,并可以扩展或修改其功能

2.1 继承的目的

  • 代码复用:子类可以直接使用父类的属性和方法,无需重复编写。

  • 类层次结构:通过继承建立逻辑上的“is-a”关系。

  • 多态支持:继承是实现多态的基础。

 2.2 继承的特点

  • 使用extends关键字定义子类。

  • 单继承:Java 只支持单继承(一个子类只能有一个直接父类),但是一个父类能有多个子类。

  • 隐式继承:所有类默认继承Object类(Java 的根类)。

  • 如果子类对父类的方法进行重写,会调用子类的方法。                                                  :被final修饰的方法不能被重写

  • 想实现同时继承两个类,可以通过继承链的方法实现,即C继承B,B继承A,相当于C继承B和A,实现继承多个类。

  • 如果父类被final关键字修饰,其属性及方法不能被子类继承。

注:方法重载与方法重写的区别

  • 方法重载:方法名相同,入参不同(数量,类型)
  • 方法重写:子类中编写方法名与父类中方法名相同的方法,之后通过子类不能调用父类被重写的方法

2.3  示例代码

2.3.1 父类

public class Parent {public int age;public String name;public void run() {System.out.println("Parent run");}public void eat() {System.out.println("Parent eat");}
}

2.3.2 子类

public class Child extends Parent{public void m1() {System.out.println("Child run");//调用父类的eat()方法eat();super.eat();}public void eat() {System.out.println("Child eat");}public Child() {//默认调用父类的无参构造方法super();//this();   //调用自己的构造方法,但this()和super()同时出现,两者都要在第一行}	
}

2.3.3 测试及结果

public class Test {public static void main(String[] args) {Child aa = new Child();aa.run();aa.m1();}
}

Parent run
Child run
Child eat
Parent eat

 2.4 继承的关键

  1. super关键字

    • 访问父类的属性/方法:super.方法名()

    • 调用父类构造方法:super()(必须在子类构造方法的第一行)

  2. 方法重写(Override)

    • 子类重新定义父类的方法(方法名、参数、返回类型必须相同)。

  3. 访问权限控制

    • 子类可以继承父类的publicprotected成员。

    • 父类的private成员对子类不可见(需通过公共方法访问)。

  4. 构造方法链

    • 子类构造方法必须调用父类构造方法(显式或隐式)。

    • 若父类没有无参构造方法,子类必须显式调用super()

三、多态

Java 多态允许同一操作作用于不同对象时产生不同的行为。多态的核心是“一个接口,多种实现”,通过继承和接口实现代码的灵活性与可扩展性。

3.1 多态的目的

  • 提高代码灵活性:同一方法可以根据对象类型动态执行不同逻辑。

  • 降低耦合性:代码依赖于抽象(父类或接口),而非具体实现。

  • 增强可扩展性:新增子类时无需修改现有调用代码。

3.2 多态的实现

  • 方法重写:子类重写父类方法。

  • 向上转型:父类引用指向子类对象(例如Animal cat = new Cat())。

  • 继承:要实现多态必须要实现继承。

3.3 多态的限制

  • 无法重写静态方法:静态方法属于类,与对象无关。

  • 无法重写private、final方法:这些方法不可被修改。

  • 属性没有多态性:属性访问由引用类型决定,而非实际对象类型。

3.4 基于继承的多态

3.4.1 相关代码

//A.java
public class A {public String show(D obj) {return "A and D";}public String show(A obj) {return "A and A";}
}//B.java
public class B extends A{public String show(Object obj) {return "B and B";}public String show(A obj) {return "B and A";}
}//C.java
public class C extends B{}//D.java
public class D extends B{}

3.4.2 测试结果

public class Test1 {public static void main(String[] args) {A a1 = new A();A a2 = new B();B b = new B();C c = new C();D d = new D();System.out.println("1:"+a1.show(b));System.out.println("2:"+a1.show(c));System.out.println("3:"+a1.show(d));System.out.println("4:"+a2.show(b));System.out.println("5:"+a2.show(c));System.out.println("6:"+a2.show(d));System.out.println("7:"+b.show(b));System.out.println("8:"+b.show(c));System.out.println("9:"+b.show(d));}
}

 运行结果

1:A and A
2:A and A
3:A and D
4:B and A
5:B and A
6:A and D
7:B and A
8:B and A
9:A and D

3.4.3 详细解释

(1)a1为A类型的对象,有show(A)和show(D)两种方法,b为B类型数据,B又继承A,向上转型,因此执行show(A),即A and A;

(2)c为C类型数据,C继承B,B又继承A,向上转型,因此执行show(A),即A and A;

(3)d为D类型数据,直接执行show(D),即A and D;

(4)A a2 = new B(); 先创建父类即A,再创建子类即B,a2指向父类,因为show(A)方法被B重写,因此此时能执行A中show(D)以及B中show(A),b为B类型数据,B又继承A,向上转型,因此执行show(A),即B and A;

(5)c为C类型数据,C继承B,B又继承A,向上转型,因此执行show(A),即B and A;

(6)d为D类型数据,直接执行show(D),即A and D;

(7)b为B类型数据,又是A的子类,因此会继承A中的方法,又因为show(A)方法被B重写,因此此时能执行A中show(D)以及B中show(A)和show(Object),B又继承A,向上转型,因此执行show(A),即B and A;

(8)C继承B,B又继承A,向上转型,因此执行show(A) ,即B and A;

(9)d为D类型数据,直接执行show(D),即A and D;

3.5 instanceof 

即使两个类之间没有继承关系,通过强制类型转换可以实现两个类之间的转换,编译成功,但是运行会报错。

Parent xx = new GrandSon1();
Child2 yy = (Child2)xx;

Child1继承Parent, GrandSon1继承Child1,Child2与GrandSon1没有继承关系。

运行结果

为了避免这种情况发生,可以在强制类型转换前用 instanceof 判断xx是否为Child2类型的对象,或者Child2子孙后代的对象。

Parent xx = new GrandSon1();
if(xx instanceof Child2) {Child2 zz = (Child2)xx;System.out.println("可转");
}else {System.out.println("不可转");}

运行结果

 不可转

补充父类转子类可以通过强制类型转换编译成功,但是数据可能改变,运行时会报错。 

相关文章:

  • 通过Ollama读取模型
  • CSS 锚点滑动效果的技术
  • 【C/C++】高阶用法_笔记
  • Tensorflow2保存和加载模型
  • 【Redis】缓存穿透、缓存雪崩、缓存击穿
  • Java 异常处理之 BufferUnderflowException(BufferUnderflowException 概述、常见发生场景、避免策略)
  • C 语言学习笔记(8)
  • 因果推断 | 用SHAP分值等价因果效应值进行反事实推理
  • 【Linux】掌握 setsid:让进程脱离终端独立运行
  • 东芝新四款产品“TB67Z830SFTG、TB67Z830HFTG、TB67Z850SFTG、TB67Z850HFTG系列三相栅极驱动器ic三相栅极驱动器IC
  • 软件测试--入门
  • 【Linux】Ext系列文件系统
  • 鸿蒙-5.1.0-release构建编译环境
  • Oracle中的select1条、几条、指定范围的语句
  • 每日算法-250514
  • 【golang】网络数据包捕获库 gopacket
  • 嵌入式系统中WAV音频文件格式详解与处理实践
  • 【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】
  • Lightpanda开源浏览器:专为 AI 和自动化而设计的无界面浏览器
  • 安卓基础(Bitmap)
  • 基金经理调仓引发大金融板块拉升?公募新规落地究竟利好哪些板块
  • 在笔墨金石间,看胡问遂与梅舒适的艺术对话
  • 威尼斯建筑双年展总策划:山的另一边有什么在等着我们
  • 牧原股份子公司与养殖户种猪买卖纠纷案一审胜诉
  • 食用城市|食饭识人
  • 通辽警方侦破一起积压21年的命案:嫌疑人企图强奸遭反抗后杀人