【构造方法】这或许是讲的最好的关于Java构造方法的文章!!

致读者

对于看到这篇博客的你们,其实不需要刻意的去记这些知识,可以收藏起来,有事没事翻开看看,这些其实看得多了,自然就烂熟于心了,如果你只是刻意的记忆了一遍,那其实你很快就会忘记,即使你当时看完可能觉得懂了,但事实上你很快就会忘了,过几个星期,你根本回忆不起来,感觉好像没看过这篇文章似的。所以说,赶紧先收藏,随时拿出来看,不然真的吃亏。

前言

Java语言中,类的构造方法是一种很特殊的方法。关于构造方法要记忆和理解的知识点其实挺多的,这个知识点其实初学的时候也一直困扰着我,因此接下来,我就来详细的讲讲构造方法,相信看过这篇文章之后,读者会对构造方法有一个比较深刻的认识和理解。

正文

首先来说说构造方法的三个特点:
一、构造方法的名称必须与类的名称相同。比如类的名称叫A,那么它的构造方法必须也叫A。
二、构造方法的前面不能声明返回值类型,即便是void也不行。只有满足了这两个条件,编译器才会认定这个方法是构造方法。
三、如果程序员没有在类中定义构造方法,那么在编译阶段,编译器会“免费赠送”给这个类一个构造方法。编译器给类赠送的这个构造方法是一个没有参数的构造方法。至于说编译器送给我们的这个构造方法里面有什么内容,咱们一会儿再说。

说完了构造方法的特点,我们再来说说构造方法的作用。很多书或者一些B站的视频上都把构造方法的作用说成是为了创建一个对象,其实这种理解是有问题的。必须承认,我们创建一个类的对象必须要调用构造方法,但构造方法的作用其实并不是为了创建对象,而是为了“初始化对象的内部状态”。“初始化对象的内部状态”这句话听起来不太好理解,其实就是为了给对象的各个属性赋初始值。我们来看一个例子:

我们定义了一个Person类,并且给Person类定义了两个属性,分别是String类型的name和int类型的age,并且还定义了一个printInfo()方法,用来打印这两个属性的值。接下来我们在main方法中创建两个Person类对象

执行程序的结果如下图:

我们发现,这两个对象的name属性和age属性的值都是默认的那个初始值,这种初始值其实没有太大意义。如果我们希望在创建对象的时候给就对象的两个属性赋上有意义的值,此时我们就可以把给属性赋值的语句写到构造方法当中。

有了构造方法之后,我们再次执行main方法,得到的结果是这样的:

从运行结果上来看,两个对象的属性都被赋予了有意义的值。但是问题来了:按照这样的写法,我们所创建的每个Person对象,name属性都被赋值为“张三”,而age属性都被赋值为20。这说明我们创建的对象是“千篇一律”的,并且从情理上也说不通,毕竟每个人都有属于自己的名字和年龄,不可能每个人都叫张三年龄20岁。

那么,如何在创建对象的时候,为每个对象都初始化属于自己的真实数据呢?这时候,我们就要用有参数的构造方法来搞定这个问题了。我们可以给构造方法添加两个参数,通过参数把数据传递给对象的属性

当我们给构造方法添加了两个参数之后,却发现main方法中原来本来正确的代码出现了语法错误

这是为什么呢?就是因为我们给Person类的构造方法添加了参数,现在Person类当中已经没有无参数的构造方法了,既然Person类当中已经没有了无参数的构造方法,那么我们在main方法中调用Person类无参数的构造方法,肯定会报错。

有人会问:编译器不是会“免费赠送”给每个类一个无参数的构造方法吗?那个送来的构造方法哪去了?这里需要特别说明一下:编译器“赠送”给类无参数构造方法是有条件的,这个条件就是:程序员没有为类定义构造方法。也就是说:只有程序员没有为类添加构造方法的情况下,编译器才会在编译的时候给这个类去自动添加一个无参数的构造方法,现在,程序员已经给Person类定义了构造方法,那么编译器就不会再给这个类添加构造方法了。

好,回归正题,现在我们想修改这个语法错误很简单,只要在main方法中给Person类的构造方法传递适当的参数就可以了

给构造方法传递了参数之后,语法错误自然消失。再次运行程序,会得到这样的结果

大家可以看到,这一次,我们就能够按照我们的意愿,创建出有自己个性化的对象了。通过这个例子我们可以看出:构造方法的作用是给对象的各个属性赋上合理的初始值,从而使得我们所创建的对象不再是“千篇一律”,而是“千姿百态”。

那么,现在我们可以再来思考两个问题:第一个问题:构造方法可以像普通方法那样实现重载吗?这是完全没有问题的,我们可以在一个类中定义多个构造方法,只要这些构造方法参数不同,就构成了重载。第二个问题:在一个构造方法中,可以调用另外一个构造方法吗?也没有问题,但调用的时候,需要注意:不能像调用普通方法那样,通过类名去调用,而是需要用一个关键字this。但是这种调用也有两个条件:
一、调用构造构造方法的语句必须放在第一行。
二、两个构造方法不能形成相互调用关系。为了方便表述,我们把一个类中的两个构造方法代称为X和Y。如果我们在X中调用了Y,那么就不能在Y中去调用X了。否则就会形成循环依赖关系,我们来看下面的例子

我们在一个构造方法中调用了另一个构造方法,调用的时候,需要用到this关键字,并且把调用语句写到第一行,这样才能顺利通过编译。

以上我们讲解的都是关于构造方法的基本常识,在这个讲解的过程中,并没有设计到类的继承关系。如果涉及继承关系,构造方法在定义和调用的过程中也有一些必须了解的知识点。
首先必须清楚,如果我们创建的是一个子类的对象,那么在创建这个子类对象的时候,虚拟机会先调用父类的构造方法,之后才去调用子类的构造方法。这个顺序不能错,否则会出现语法错误。为了说明问题:我们先来给Person类添加一个无参数的构造方法,并在构造方法中输出一句”父类的构造方法”

之后我们再定义出一个Person类的子类Student,并且在子类中也定义一个无参数的构造方法,在构造方法中输出一句”子类的构造方法“

之后,我们在main方法中创建一个子类对象

运行main方法,得到结果如下图:

很多人不明白,在子类的构造方法中,只是输入了“子类的构造方法”这样一句话,控制台上为什么同时还输出了“父类的构造方法”?原因就是我们刚才所说的:调用子类构造方法的时候,会首先调用父类的构造方法。即使程序员没有写代码去调用父类的构造方法,编译器也会把调用父类构造方法的语句补充添加到代码中。

那么,补充添加调用父类构造方法的代码,是如何实现的?这里必须先讲一下子类调用父类构造方法的语法细节:
一、子类调用父类构造方法的时候,不能通过构造方法本身的名称来调用,必须使用super关键字。
二、子类在它的普通方法中不能调用父类的构造方法,只能在它自身的构造方法中才能调用。
三、子类调用父类构造方法的语句,必须写在自身构造方法的第一行。
这三条语法规则至关重要,请牢记。按照这个语法规则,编译器看到程序员没有在子类构造方法中调用父类构造方法,会按下图所示的方式把调用父类构造方法的语句添加到代码中

通过上图可以看到,如果程序员没有在子类构造方法中添加调用父类构造方法的语句,编译器会自动把那条调用语句补充进来,并且放到子类构造方法的第一行。在文章一开始提出了一个问题:编译器会在赠送给我们的构造方法中添加什么内容,此时你应该明白了吧?就是因为在子类的构造方法中调用了父类的构造方法,所以我们才会在控制台上会看到两条输出语句。

现在又冒出一个问题:父类如果有好几个构造方法,编译器会自动调用哪一个呢?这里必须明确:编译器只会调用那个无参数的构造方法,不会调用有参数的构造方法。这个规则又会引发一个新的问题,那就是:如果父类中压根就没有无参数的构造方法,那怎么办?在这种情况下,编译器就会强制子类定义一个构造方法,并且在它的构造方法中,通过手动调用的形式去调用父类的构造方法,如果你不那么干,编译器就会使出它的杀手锏:划红线!来看下图:

既然无论程序员是否愿意,子类在它的构造方法当中必须要调用父类的构造方法,那么,通常情况下我们应该怎样调用父类构造方法才算合理呢?一般来讲,子类都会比父类拥有更多的属性。就本文而言,父类(Person)有2个属性,分别是name和age,而子类(Student)有3个属性,分别是name、age和num。当然,子类的3个属性当中,有2个是从父类那里继承过来的。在创建一个Student对象的时候,必须对这3个属性进行初始化。所以通常子类的构造方法会定义3个参数,这3个参数分别用来初始化子类的3个属性。既然子类的3个属性当中,有2个是继承于父类的,那么就可以用父类的构造方法去初始化那2个继承来的属性,而剩下的那个由子类自身所定义的属性num,可以在子类自身构造方法中实现初始化,看下图

通常来讲,子类就是这样调用父类构造方法的。
最后再回答一个问题:普通方法的名称可以与类名相同吗?答案是:可以!在这种情况下,编译器区分该方法是普通方法还是构造方法,就看方法的前面有没有声明返回值类型。这就是为什么Java语言规定构造方法不能有声明返回值类型的原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349974.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

仰暮计划|“以前老一辈农村人真的是穷极了……苦极了……”

仰暮计划|“以前老一辈农村人真的是穷极了……苦极了……” 回首往事,几十年的坎坷经历难以件件叙述,却又历历在目。以前老一辈农村人真的是穷极了……苦极了……我奶奶是1941年生人,用她的话说就是“命很硬”。我爷爷1940年生人,…

[TII 2023] 基于压缩感知的多级隐私保护方案

Multilevel Privacy Preservation Scheme Based on Compressed Sensing | IEEE Journals & Magazine | IEEE Xplore 摘要 物联网的广泛应用在给人们带来便利的同时,也引发了人们对数据采集、分析和共享过程中隐私泄露的担忧。本文提出了一种基于压缩感知的多级…

电商系统设计到开发03 引入Kafka异步削峰

一、前言 系统设计:电商系统设计到开发01 第一版设计到编码-CSDN博客 接着上篇文章:电商系统设计到开发02 单机性能压测-CSDN博客 本篇为大制作,内容有点多,也比较干货,希望可以耐心看看 已经开发的代码&#xff0…

【行业应用-智慧零售】东胜物联餐饮门店智能叫号解决方案,为企业智能化升级管理服务

随着科技的不断进步,物联网设备已经广泛应用于各行各业,包括餐饮业。在餐饮门店的线下运营过程中,叫号系统是一项重要的设备需求。传统的叫号方式往往会消耗大量的人力和时间,而物联网技术为餐饮行业提供了一种更高效、智能化的解…

幻兽帕鲁服务器数据备份

搭建幻兽帕鲁个人服务器,最近不少用户碰到内存不足、游戏坏档之类的问题。做好定时备份,才能轻松快速恢复游戏进度 这里讲一下如何定时将服务器数据备份到腾讯云轻量对象存储服务,以及如何在有需要的时候进行数据恢复。服务器中间的数据迁移…

【论文阅读】GraspNeRF: Multiview-based 6-DoF Grasp Detection

文章目录 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Using Generalizable NeRF针对痛点和贡献摘要和结论引言模型框架实验不足之处 GraspNeRF: Multiview-based 6-DoF Grasp Detection for Transparent and Specular Objects Us…

为什么TestNg会成为Java测试框架的首选?还犹豫什么,看它!

上一篇自动化测试我们大概了解了测试的目标、测试的技术选型以及搭建平台的目标及需求,也确定了自动化测试方案以testNg作为整个测试流程贯穿的基础支持框架,那么testNg究竟有什么特点?本篇开始我们来详细的学习testNg这个测试框架。 为什么要…

qwt直角坐标 画sing(x)/x

cmath的常见函数&#xff1a;qPow()求平方&#xff0c;log(&#xff09;对数10为底 角度转弧度&#xff1a;x(angel/180)*M_PI 图示&#xff1a; 头文件&#xff1a; #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <qwt_plot.h> #in…

使用 CDC MinIO 汇入端为 CockroachDB 保持持久数据

CockroachDB 数据库迅速崭露头角&#xff0c;作为一个坚韧且可扩展的分布式 SQL 数据库。它从其昆虫名字的坚持不懈中汲取灵感&#xff0c;即使面对硬件故障&#xff0c;CockroachDB 也能保证高可用性。其分布式架构横跨多个节点&#xff0c;类似于其昆虫原型的适应性。 凭借强…

SpringCloud Aliba-Seata【下】-从入门到学废【8】

目录 1.数据库创建 1.seata_account库下建表 2.seata_order库下建表 3.seata_storage库下建表 4.在每个库下创建回滚日志 2.创建订单模块 2.1建工程 2.2加pom 2.3改yml 2.4file.conf 2.5registry.conf 2.6domain 2.7Dao 2.8Service 2.9controller 2.10confi…

阅读go语言工具源码系列之gopacket(谷歌出品)----第一集 DLL的go封装

gopacket项目是google出品的golang第三方库&#xff0c;项目源码地址google/gopacket: Provides packet processing capabilities for Go (github.com) gopacket核心是对经典的抓包工具libpcap(linux平台)和npcap(windows平台)的go封装&#xff0c;提供了更方便的go语言操作接…

36、WEB攻防——通用漏洞XSS跨站MXSSUXSSFlashXSSPDFXSS

文章目录 MXSSUXSSFlashXSSPDF XSS 跨站的艺术-XSS入门与介绍 UTF-7 XSS、MHTML XSS、CSS XSS、VBScript XSS已经过时&#xff0c;基本上不会出现。 MXSS 简单来说&#xff0c;就是你往前端页面插入payload&#xff0c;但是前端有些防御策略会将payload编码&#xff0c;导致…

防火墙综合实验

实验需求&#xff1a; 1、生产区在工作时间内可以访问服务器区&#xff0c;仅可以访问http服务器。 2、办公区全天可以访问服务器区&#xff0c;其中&#xff0c;10.0.2.20可以访问FTP服务器和HTTP服务器&#xff0c;10.0.2.10仅可以ping通10.0.3.10。 3、办公区在访问服务器…

【VBA代码解决方案】md文档转Word后,全自动转换为标准的Word公式格式

【VBA解决方案】全自动将Word中的文本公式转换为标准公式 写在最前面VBA代码全自动方法将md文档导出为word代码如何运行VBA代码注意事项 一些如何实现的回忆记录步骤解析手动将文本转换为Word公式代码逻辑步骤设想代码解析代码解释总结 其他背景介绍应用场景VBA脚本介绍如何使用…

信息安全认证首选CISP-PTE

&#x1f525;在信息安全领域&#xff0c;CISP-PTE认证正逐渐成为行业的新星。作为中国信息安全测评中心推出的专业认证&#xff0c;CISP-PTE为信息安全从业者提供了国内Z高标准的资质培训。 &#x1f3af;为什么选择CISP-PTE&#xff1f; 1️⃣业界认可&#xff1a;CISP-PTE是…

JAVA_EE_api_中英文对照版

点击即可下载&#xff1a; JAVA_EE_api_中英文对照版

STM32标准库——(3)GPIO输入

1.按键简介 按键&#xff1a;常见的输入设备&#xff0c;按下导通&#xff0c;松手断开 按键抖动&#xff1a;由于按键内部使用的是机械式弹簧片来进行通断的&#xff0c;所以在按下和松手的瞬间会伴随有一连串的抖动 1.1 硬件电路图 上面两个是外加上拉电阻&#xff08;常用…

Python学习从0到1 day9 Python函数

苦难是花开的伏笔 ——24.1.25 函数 1.定义 函数&#xff1a;是组织好的&#xff0c;可重复使用的&#xff0c;用来实现特定功能的代码段 2.案例 在pycharm中完成一个案例需求&#xff1a;不使用内置函数len&#xff08;&#xff09;&#xff0c;完成字符串长度的计算 #统计字…

MyBatis 批量插入数据优化

前言 最近在项目上遇到了批量插入的场景问题&#xff0c;由于每次需要插入超过 10w 的数据量并且字段也蛮多的导致如果使用循环单次插入的方式插入数据插入的效率不高。相信读者们在实际开发中也遇到过这样类似的场景&#xff0c;那么批量插入如何实现呢&#xff1f; 其实我也…

分寝室

L1-7 分寝室 分数 20 作者 陈越 单位 浙江大学 学校新建了宿舍楼&#xff0c;共有 n 间寝室。等待分配的学生中&#xff0c;有女生 n0​ 位、男生 n1​ 位。所有待分配…