news 2026/3/29 23:46:30

面向对象编程三大特性:封装、继承、多态的核心要义

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面向对象编程三大特性:封装、继承、多态的核心要义

封装

封装是面向对象编程的基本原则,封装要求在编写类时,对外隐藏内部的数据状态和实现细节,仅对外暴露接口,用于外部调用访问。

类的封装,通常类的属性私有(用private修饰符),不对外暴露数据和实现细节,而是通过get和set方法获取和设置属性。

packageoop.classDemo2;publicclassTeacher{// 私有,不对外公开访问的实例属性privateStringname;privateintage;// 构造方法(方法重载)publicTeacher(Stringname,intage){this.name=name;this.age=age;}publicTeacher(Stringname){this.name=name;}publicTeacher(intage){this.age=age;}publicTeacher(){}// 实例方法publicvoidsetName(Stringname){this.name=name;}publicStringgetName(){returnthis.name;}publicvoidsetAge(intage){this.age=age;}publicintgetAge(){returnthis.age;}publicvoidsayWhoIam(){System.out.println("我叫"+this.name+",今年"+this.age+"岁,我是一名老师");}}

类的使用者,不能通过new一个对象,用对象.属性设置和获取数据,只能通过对象.方法设置和获取数据。

TeacherxiaoMing=newTeacher("小明",33);System.out.println(xiaoMing.age);// 错误代码,不能通过对象.属性名称 来访问属性System.out.println(xiaoMing.getAge());// 正确代码,通过get方法,来访问属性

为什么要这么做?为什么要多此一举编写get和set方法?

这样做的好处是:

  1. 有利于多人团队协作。类的编写者和调用者可以分开,类的调用者不需要关心和了解类的具体属性是什么,只需要调用方法(调用API)实现需要的操作即可。
  2. 便于维护和更新代码。编写一个类可以使用多种数据结构、不同的数据类型,如果属性的访问不是通过封装成方法,那更新编写类的数据结构,则调用类的代码也需要同步变更。而使用封装的方法,则在调用时不需要更新,因为类更换数据结构后,只需要更新适配新数据结构的get和set方法即可。
  3. 利于代码的安全性。通过set方法设置变量属性,可以做数据校验和特殊处理,有利于代码的安全性。

**注意:封装并不是要求把所有的私有属性通过setter和getter暴露出来,因为开放私有属性获取和设置,这本身可能就破坏了类的封装性

很多时候,类不提供setter和getter方法,而是直接提供业务相关的方法。

publicclassBankAccount{privatedoublebalance;publicBankAccount(){this.balance=0;}// 不直接提供setBalance,而是提供业务相关的方法publicvoiddeposit(doubleamount){if(amount>0){// 判断金额是否合法balance+=amount;}}publicbooleanwithdraw(doubleamount){if(amount>0&&balance>=amount){balance-=amount;returntrue;}returnfalse;}publicdoublegetBalance(){returnbalance;}// 注意:没有setBalance方法!}

继承

面向对象的编程,是以类来组织和封装代码。当类足够多时,我们会对类进行抽象,划分为所谓父类和子类,比如“动物”这个父类下,有“哺乳动物”、“脊椎动物”等子类。

从认知上,子类和父类一定有一些共同的属性特征,否则不可能抽象成一个父类。而子类一定会与父类有些差异或者特殊属性,否则页不可能被划分为子类。就像父类“教师”,可以划分为“生物教师”、“数学教师”子类。“数学教师”是(is a)“教师”,而“数学教师”又具备“教数学”特殊技能的特殊的“教师”。

什么是面向对象编程的继承?面向对象编程时,子类可继承父类的公开(public)属性和方法,这一特性可以大幅减少代码量,提高编程效率。

在Java中,父类又称为基类,子类又称为扩展类、派生类,因此使用关键字extends来标记子类。即

publicclassSonClassextendsFatherClass{// 子类体}

在Java中,子类可以继承父类的:

  1. 公开的静态属性
  2. 公开的静态方法
  3. 所有的实例属性,父类私有的(private)实例属性无法被直接访问,但是可以通过继承公开的(public protected)实例方法进行调用,间接获取父类的私有的实例属性。
  4. 公开的实例方法
    需要注意的是,子类不继承父类的构造方法,而是子类必须通过super()调用父类的构造方法。
publicclassApp{publicstaticvoidmain(String[]args){// MathTeacher继承Teacher的公开的静态属性System.out.println(MathTeacher.CLASS_NAME);// 老师// MathTeacher继承Teacher的公开的静态方法MathTeacher.sayHello();// Hello everyone, I am a teacher// MathTeacher继承Teacher的公开的实例属性MathTeacherzhangSan=newMathTeacher("张三",32);System.out.println(zhangSan.name);// 张三(name为父类的公开的实例属性)// MathTeacher继承Teacher的公开的实例方法System.out.println(zhangSan.getAge());// 32(age为父类的私有实例属性,通过公开的实例方法间接访问)}}
publicclassTeacher{// 静态属性publicstaticfinalStringCLASS_NAME="老师";// 静态方法publicstaticvoidsayHello(){System.out.println("Hello everyone, I am a teacher");}// 实例属性(一般是要封装成私有属性,此处为示例继承功能,两个属性分别用公开和私有)publicStringname;privateintage;// 构造方法publicTeacher(Stringname,intage){this.name=name;this.age=age;}// 实例方法publicintgetAge(){returnage;}}
publicclassMathTeacherextendsTeacher{// extends关键字继承父类// 继承了父类的公开的静态属性// 继承了父类的公开的静态方法// 继承了父类的公开的实例属性// 子类需要使用super()调用父类的构造方法publicMathTeacher(Stringname,intage){super(name,age);}// 继承了父类的公开的实例方法}

super

子类会继承父类的实例属性,子类构造方法需要使用super关键词,调用父类构造方法,初始化继承自父类的实例属性。

子类的构造方法,会隐式的调用super()。但是,如果父类的构造方法是有参构造,则子类必须显性的编写super()方法进行调用。如果显性编写super(),比如:

// 父类publicclassTeacher{privateStringname;privateintage;publicTeacher(){System.out.println("父类初始化了");}}
// 子类publicclassMathTeacherextendsTeacher{publicMathTeacher(){System.out.println("子类初始化了");}}
// 子类初始化publicclassApp{publicstaticvoidmain(String[]args){MathTeacherzhangSan=newMathTeacher();}}
父类初始化了 子类初始化了 进程已结束,退出代码为0

初始化子类时,会调用子类的构造方法。而在子类的构造方法内部,会隐式的调用super(),即调用父类的构造方法。因此,才会运行System.out.println(“父类初始化了”)。

需要注意: super()必须是子类构造方法的第一个语句。

方法重写

子类会继承父类公开的实例方法,但是很多情况下,父类的方法可能并不是子类需要的,或者子类需要的实例方法,运行逻辑与父类不同。这种情况下,就可以在子类重新定义与父类方法相同名称的实例方法,在实例调用时,会去运行子类定义的方法。这种情况,叫方法的重写。

子类重写的方法,可添加@override注解(非必须),可以帮助编译器检查方法重写是否正确。

需要注意:

  1. 方法重写指的是实例方法的重写,静态方法不存在重写。也就是父类和子类都存在相同的静态方法,此类情况并非方法的重写。
  2. 方法的重写,要求子类和父类方法的方法名、方法参数和范围值都相同,否则系统不会认定是方法的重写。
  3. 访问修饰符不能比父类更严格。(宽松程度:public > protected > default > private)
  4. 抛出异常:不能抛出比父类方法更宽泛的检查异常

Object类

Java是用类来组织代码,java中所有的类都隐式的继承自一个Object类,继承Object类的方法,比如使用hashcode、toString等方法。

多态

多态是指同一个方法,在不同的对象上调用,会产生不同的效果,。

多态是方法的多态,跟属性没有半毛钱关系。

面向对象的多态特性,表现在方法重载和方法重写。

方法重载的多态(编译时多态/静态多态)

方法重载,是指在java的同一个类中,可以定义多个具有相同方法名的方法,只需要满足:返回类型、方法参数(参数数量、参数类型、参数顺序)不同。

在方法被调用时,系统会根据形参自动选择对应的方法(在编译阶段,编译器会根据形参,绑定选用的方法,是静态绑定)。比如:

// 方法重载示例:同一个类中,方法名相同,参数列表不同classCalculator{// 加法方法的不同形式publicintadd(inta,intb){returna+b;}publicdoubleadd(doublea,doubleb){returna+b;}publicintadd(inta,intb,intc){returna+b+c;}}publicclassOverloadExample{publicstaticvoidmain(String[]args){Calculatorcalc=newCalculator();// 编译器根据参数类型和数量决定调用哪个方法System.out.println("两个整数相加: "+calc.add(5,10));// 调用 add(int, int)System.out.println("两个小数相加: "+calc.add(5.5,10.5));// 调用 add(double, double)System.out.println("三个整数相加: "+calc.add(5,10,15));// 调用 add(int, int, int)}}

方法重写的多态(运行时多态/动态多态)

方法重写,是发生在子类继承父类的场景里。方法重写,就是子类继承父类方法时,对相同的方法的代码逻辑进行重新编写。

当父类引用指向子类对象时,系统会动态的根据子类对象,调用子类对象的方法(在编译阶段,编译器会检查父类是否有需要调用的方法,而在运行阶段,系统会根据子类对象调用不同的方法,因此是动态绑定)。

// 父类classAnimal{publicvoidmakeSound(){System.out.println("动物发出声音");}}// 子类1classDogextendsAnimal{// 方法重写@OverridepublicvoidmakeSound(){System.out.println("汪汪汪!");}// 子类1狗特有的方法publicvoidwagTail(){System.out.println("狗摇尾巴");}}// 子类2classCatextendsAnimal{// 方法重写@OverridepublicvoidmakeSound(){System.out.println("喵喵喵!");}}// 子类3classBirdextendsAnimal{// 方法重写@OverridepublicvoidmakeSound(){System.out.println("叽叽喳喳!");}}publicclassPolymorphismExample{publicstaticvoidmain(String[]args){// 运行时多态:父类引用指向子类对象AnimalmyAnimal;myAnimal=newDog();// Animal引用指向Dog对象myAnimal.makeSound();// 输出:汪汪汪!myAnimal=newCat();// Animal引用指向Cat对象myAnimal.makeSound();// 输出:喵喵喵!myAnimal=newBird();// Animal引用指向Bird对象myAnimal.makeSound();// 输出:叽叽喳喳!// 示例:多态在数组中的应用Animal[]animals=newAnimal[3];animals[0]=newDog();animals[1]=newCat();animals[2]=newBird();System.out.println("\n动物合唱:");for(Animalanimal:animals){animal.makeSound();// 同一方法调用,不同行为}}}

方法重写是实例方法的重写,静态方法没有重写。静态方法可以被子类“隐藏”(hide),而不是重写。调用哪个版本取决于引用类型,而不是对象类型。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/28 15:21:38

服务器文件管理太麻烦?宝塔 FTP+cpolar 让远程操作像本地一样简单

文章目录前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结5. 固定FTP公网地址6. 固定FTP地址连接**宝塔 FTP 让服务器文件管理变得简单,而 cpolar 则打破了局域网的限制,两者结合为远程文件操作提供了安全、高效的解决…

作者头像 李华
网站建设 2026/3/28 10:24:12

Web3.js钱包与账户管理

简介 Web3.js Wallet是我们在想要直接使用私钥进行任何区块链操作(交易)时的主要入口点,在其它库中也被称为Signer。 与其它只能保存一个账户的库不同,Web3.js Wallet可以保存多个账户,每个账户都有它自己的私钥和地…

作者头像 李华
网站建设 2026/3/26 3:29:19

Java 虚拟机(JVM)内存模型与垃圾回收机制研究

Java 虚拟机(JVM)是Java跨平台特性的核心,其内存模型与垃圾回收(GC)机制是Java领域的重要学术研究课题,直接决定了Java程序的运行效率与稳定性。JVM 内存模型将运行时数据区分为方法区、堆、虚拟机栈、本地…

作者头像 李华
网站建设 2026/3/23 18:46:54

Java 面向对象设计模式的应用与设计原则

设计模式是Java面向对象编程的高级应用形式,是对软件开发中常见问题的标准化解决方案,也是Java学术研究与工程实践的重要结合点。GoF(四人组)提出的23种设计模式,基于封装、继承、多态的核心特性,将代码设计…

作者头像 李华
网站建设 2026/3/26 21:40:09

AC15启动项分析,漏洞分析

1、固件模拟sudo chroot . sh /bin/httpd第一个问题,监听ip有问题我们需要配置网卡sudo brctl addbr br0sudo ifconfig br0 192.168.100.3这里我们设置br0网卡,启动web成功启动,这里监听的就是我们设置的ip这里我们可以运行这个脚本&#xff…

作者头像 李华
网站建设 2026/3/23 11:16:14

二、python语法基础

一、前言与概述前面了解了python安装以及环境的准备,下面是关于python语法基础的一个概要:二、语法内容(一)、基础语法开始之前:注释代码# 单行注释 """ 多行注释 """多行注释 1、变量与…

作者头像 李华