当前位置: 首页 > 编程日记 > 正文

java静态/动态成员变量、初始化块,父类/子类构造函数执行顺序问题

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

  1. /*
  2. * 几大原则
  3. * 一、静态成员变量(Static)
  4. * 1、静态成员变量为类变量,所有对象共享同一内存空间
  5. * 2、静态成员变量的声明和定义仅在首次加载类时执行一次
  6. * 3、首次加载类时首先对所有静态成员变量根据类型默认赋初值,然后再对有右值的附右值
  7. * 二、静态初始块
  8. * 1、静态初始化块仅在首次加载类时执行一次
  9. * ······多个静态成员变量与静态始化快参照出现顺序先后执行······
  10. * 三、动态成员变量
  11. * 1、动态成员变量定义在每次实例化对象时在构造函数之前执行
  12. * 四、动态初始化块
  13. * 1、动态初始化块在每次实例化对象时在构造函数之前执行
  14. * ······多个动态成员变量与动态初始化块参照出现顺序先后执行······
  15. * 总结:总的来说,在不涉及继承的前提下,当首次加载类时,按照如下顺序执行
  16. * 1、按照出现顺序先后执行静态成员变量定义与静态初始化块
  17. * 2、按照出现顺序先后执行动态成员变量定义与动态初始化块
  18. * 3、执行构造函数
  19. * 再次实例化对象时只执行第2、3步即可
  20. *
  21. * ············成员变量与定义与初始化块先于构造函数执行·········
  22. * 五、当涉及到继承时,按照如下顺序执行
  23. * 1、执行父类的静态成员变量定义与静态初始化块,执行子类的静态成员变量定义与静态初始化块
  24. * 2、执行父类的非静态成员变量定义与动态初始化块,执行父类构造方法
  25. * 3、执行子类的非静态成员变量定义与动态初始化块,执行子类构造方法
  26. * 另:父类构造方法中用到的方法如果已被子类重写,那么在构造子类对象时在调用父类构造函数中使用子类重写的方法
  27. */


1.实例变量和类变量的内存分配

类变量 :使用static修饰的成员变量是类变量,属于该类本身

实例变量:没有使用static修饰的成员变量是实例变量,属于该类的实例

由于同一个JVM内每个类只对应一个Class对象,因此同一个JVM内的一个类的类变量只需一块内存空间

对于实例变量而言,该类每创建一次实例,就需要为实例变量分配一块内存空间,所以,程序中有几个实例,实例变量就需要几块内存空间

2.类变量的初始化时机总是处于实例变量的初始化之前

我们先看下下面三段代码:

1)因为两个实例变量都是在创建变量的时候才开始分配空间,此时num2还没有分配,所以前向引用就会出现编译错误。

1 int num = num2 + 3; //非法前向引用,会报错 2 int num2 = 2

2)因为两个类变量在JVM加载类的时候分配空间,此时num2还没有分配,所以前向引用就出现编译错误。

1 static int num = num2 + 3; //非法前向引用,会报错 2 static int num2 = 2

3)因为类变量num2在JVM加载类的时候空间已经分配好,而num在创建实例的时候才分配空间,此时num2已经分配成功了,所以num前向引用成功。

1 int num = num2 + 3; //正确使用 2 static int num2 = 2;

由上面三段代码块就可以验证得:类变量的初始化时机总是处于实例变量的初始化之前

3.Java对象的初始化方式及其执行顺序

Java对象的初始化方式有三种:1)构造器 2)初始化块 3)定义变量时指定初始化值

如果这三种初始化方式同时出现,也要注意,他们也有一个执行顺序的规定:

1)静态初始化块只在类第一次创建对象的时候运行一次,后面就不会再运行,而类在每次创建对象时,非静态初始化块总是会运行一次。

public class Test{static {System.out.println("执行---静态初始化代码块.");}{System.out.println("执行---非静态初始化代码块.");}public static void main(String[] args) {for (int i = 1; i <= 2; i++) {System.out.println("创建第 " + i + " 个对象"); new Test();System.out.println();}}
}




运行结果:

2)构造器每次创建对象时,构造器必然有执行的机会,此时,非静态初始化块必定也将获得机会并且运行在构造器之前

public class Test{{System.out.println("执行---非静态初始化代码块.");}public Test() {System.out.println("执行---构造器.");}public static void main(String[] args) {for (int i = 1; i <= 2; i++) {System.out.println("创建第 " + i + " 个对象"); new Test();System.out.println();}}
}




运行结果:

3)定义变量时指定的初始化值和初始化块中指定的初始值的执行顺序与他们在源程序中的排列顺序相同。

验证代码一:

public class Test{String i = "定义变量时指定的初始化值";{i = "初始化块中指定的初始值";}public static void main(String[] args) {for (int i = 1; i <= 2; i++) {System.out.println("创建第 " + i + " 个对象"); System.out.println(new Test().i);System.out.println();}}
}




运行结果

验证代码二 :

public class Test{{i = "初始化块中指定的初始值";}String i = "定义变量时指定的初始化值";public static void main(String[] args) {for (int i = 1; i <= 2; i++) {System.out.println("创建第 " + i + " 个对象"); System.out.println(new Test().i);System.out.println();}}
}




运行结果:

4.关于父子实例的内存控制

(一般情况下是不用内部类来验证的,但是都是一样的啦,我偷懒下,所以使用了内部类,大家原谅哈)

1)当子类重写父类方法后,父类表面上只是调用属于自己的被子类重写的方法。

public class Test{class Base {Base() {this.info();}public void info() {System.out.println("Base");}public void getInfo() {info();}}public class Child extends Base{@Overridepublic void info() {System.out.println("Child");}}public static void main(String[] args) {Test test = new Test();Base base = test.new Child();base.info();base.getInfo();}
}




运行结果:

2)上述是属于多态中方法的体现,但是方法有多态,实例变量无多态。

解释下“方法有多态,变量无多态”这句话:意思是,不管怎样,父类表面上只是调用属于自己的被子类重写的方法。而变量不一样,假设父类和子类都有同一个变量名的实例变量,向上转型后,通过父类访问的实例变量得到的值是自身的而非子类的。向下转型后,通过子类访问的实例变量得到的值是自身的而非父类的。

很多书上或教学视频上都讲,创建一个子类对象的时候,Java 会顺着继承结构往上一直找到 Object,然后从 Object 开始往下依次执行构造函数。先执行父类的构造函数,然后在其子类中会创建一个成员变量指向他的父类。其实这个说法是错误的系统并不会真正的去创建父类对象,只是在子类对象中不仅保存了本身的实例变量,还有它父类的全部实例变量。

public class Test{class Base {    //父类int i = 2;}public class Child extends Base{    //子类int i  = 20;}public static void main(String[] args) {Test test = new Test();Child child = test.new Child();Base base = child;System.out.println(" Base.i : " + base.i);System.out.println("Child.i : " + child.i);}
}




运行结果:

5.final修饰符

final变量在编译时就被确定下来了,相当于一个直接量。

1)final修饰的实例变量赋值时机:

  • 定义final实例变量时 指定初始值
  • 非静态初始化模块中为final实例变量指定的初始值
  • 在构造器中为final实例变量指定初始值

2)final修饰的类变量赋值时机:

  • 定义final类变量时指定初始值
  • 静态初始化模块中为final实例变量指定的初始值

转载于:https://my.oschina.net/Chaos777/blog/306492

相关文章:

什么?我要对AI礼貌?人机交互面临的道德漏洞

作者 | 库珀来源 | 数据实战派头图 | 付费下载于 IC Photo如果你在一条道路上行驶&#xff0c;突然前面拐弯处出现一辆无人驾驶汽车&#xff0c;你会继续坚持你的道路优先权&#xff0c;还是让位使它先过去&#xff1f;目前&#xff0c;我们大多数人在涉及其他人的情况下能表现…

C#多线程共享数据

在多线程编程中,我们经常要使用数据共享.C#中是如何实现的呢?很简单,只要把你要共享的数据设置成静态的就可以了.关键字static .如下: static Queue q1new Queue(); static int b0; 在这里我定义了一个整形变量b和队列q1. 接下去就可以创建多线程代码了.如下: MyThread m…

异常-----Java compiler level does not match解决方法

假如你现在还在为自己的技术担忧&#xff0c;假如你现在想提升自己的工资&#xff0c;假如你想在职场上获得更多的话语权&#xff0c;假如你想顺利的度过35岁这个魔咒&#xff0c;假如你想体验BAT的工作环境&#xff0c;那么现在请我们一起开启提升技术之旅吧&#xff0c;详情请…

求几亿个数中不重复元素的个数

题目&#xff1a; 有2.5亿个无符号整数&#xff08;但在文件里面&#xff09;&#xff0c;要求找出这2.5亿个数字里面&#xff0c;不重复的数字的个数&#xff08;那些只出现一次的数字的数目&#xff09;&#xff1b;另外&#xff0c;可用的内存限定为600M&#xff1b;要求算法…

进一步提升用户信息安全保护意识 小米安全与隐私宣传月完满落幕

6月29日&#xff0c;第二届小米安全与隐私宣传月活动完美落幕。活动通过多形式、多层次、全方位展示了小米在信息安全与用户隐私保护方面的实践和成就&#xff0c;进一步提升小米全体员工保护消费者个人信息的安全意识&#xff0c;为小米全线产品的安全防护水平奠定基础。 闭幕…

已知2个整形数据a,b.不使用if,?:以及其他任何条件判断的语法,找出a跟b中数据的大者。

已知2个整形数据a,b.不使用if,?:以及其他任何条件判断的语法&#xff0c;找出a跟b中数据的大者。答案&#xff1a; int max(int a,int b){return (ababs(a-b))/2;}类似的 请定义一个宏&#xff0c;比较两个数a、b的大小&#xff0c;不能使用大于、小于、if语句 答案&#xff1…

flume源码学习8-hdfs sink的具体写入流程

上一篇说了HDFSEventSink的实现&#xff0c;这里根据hdfs sink的配置和调用分析来看下sink中整个hdfs数据写入的过程&#xff1a; 线上hdfs sink的几个重要设置 12345678hdfs.path hdfs://xxxxx/%{logtypename}/%Y%m%d/%H&#xff1a; hdfs.rollInterval 60 hdfs.rollSize 0…

详解zabbix中文版安装部署

一、zabbix简介&#xff08;摘自百度百科&#xff09;zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。zabbix能监视各种网络参数&#xff0c;保证服务器系统的安全运营&#xff1b;并提供柔软的通知机制以让系统管理员快速定位/解决存在…

赠书 | 图解机器学习算法,看这文就够了!

机器学习指的是计算机根据给定的问题、课题或环境进行学习&#xff0c;并利用学习结果解决问题或课题等的一整套机制&#xff08;图 1-1&#xff09;。 图 1-1 分类的示意图与机器学习共同成为热门话题的还有人工智能和深度学习。这里梳理一下它们之间的关系&#xff08;图 1-…

C#获得文件版本信息及只读文件的删除

获取文件的版本信息: FileVersionInfo myFileVersionInfo1 FileVersionInfo.GetVersionInfo("D://TEST.DLL"); textBox1.Text"版本号: " myFileVersionInfo1.FileVersion; 更改文件属性&#xff0c;删除只读文件&#xff1a; 下例欲将E:/test.txt文件…

组策略 从入门到精通(二) 如何区别跨越WAN网的计算机对组策略的套用

如果客户机与DC中间跨越了网络&#xff0c;造成传输速率慢的情况&#xff0c;我们希望通过策略中的一些元素&#xff0c;达成对这些计算机的另类处理。但我们并不知道这些计算机哪些与我们DC之间属于低速连接&#xff0c;哪些属于高速连接&#xff0c;那么我们要如何通过组策略…

插入记录时单引号的处理

由于Content, Title中可能包含单引号&#xff0c;直接使用sql的insert命令会报错&#xff0c;对此有两种处理方法&#xff0c;一种将单引号替换成两个单引号&#xff0c;第2种方法是使用存储过程。 表myBBS的格式定义如下&#xff1a; CREATE TABLE [dbo].[myBBS] ( [ID] [bi…

仅用 480 块 GPU 跑出万亿参数!全球首个“低碳版”巨模型 M6 来了

继今年 3 月阿里达摩院发布国内首个千亿参数多模态大模型 M6&#xff08;MultiModality-to-MultiModality MultitaskMega-transformer&#xff0c;以下简称 M6&#xff09; 之后&#xff0c;6 月 25 日&#xff0c;达摩院宣布对 M6 进行全新升级&#xff0c;带来“低碳版”巨模…

怎样将jpg转换成pdf软件

为什么80%的码农都做不了架构师&#xff1f;>>> 怎样将jpg转换成pdf软件 序言&#xff1a; 企业或个人通常会遇到设备终端软件的兼容性和支持性问题&#xff0c;比如&#xff0c;JPG转PDF文本&#xff0c;这给等于给用户设置了一个门槛&#xff0c;遇到需要将JPG转换…

二叉树的层次遍历 II

给出一棵二叉树&#xff0c;返回其节点值从底向上的层次序遍历&#xff08;按从叶节点所在层到根节点所在的层遍历&#xff0c;然后逐层从左往右遍历&#xff09; 样例 给出一棵二叉树 {3,9,20,#,#,15,7}, 3/ \9 20/ \15 7 按照从下往上的层次遍历为&#xff1a; [[15,7],[…

jquery autocomplete实现solr查询字段自动填充并执行查询

2019独角兽企业重金招聘Python工程师标准>>> 页面引入三个JS&#xff1a; <script type"text/javascript" src"js/jquery-1.7.2.js"></script> <script type"text/javascript" src"js/jquery-ui.js">&l…

C#使用CDO发送邮件

可以引用的COM组件列表&#xff0c;发现里面有一个名为Microsoft CDO For Exchange 2000 Library的COM组件&#xff0c;就是这个&#xff0c;我们可以用它来连接SMTP Server&#xff0c;使用用户名/密码验证发送邮件。 下面是实现的一个例子&#xff1a; Smtp Server使用的Smtp…

干货 | 当 YOLOv5 遇见 OpenVINO,实现自动检测佩戴口罩

YOLOv5网络YOLOv5代码链接&#xff1a;https://github.com/ultralytics/yolov5YOLOv5 于2020年6月横空出世&#xff01;一经推出&#xff0c;便得到CV圈的瞩目&#xff0c;目前在各大目标检测竞赛、落地实战项目中得到广泛应用。 YOLOv5在COCO上的性能表现&#xff1a;YOLOv5一…

Ubuntu 16.04安装双显卡驱动方法收集

说明&#xff1a;不一定有效&#xff0c;要不断尝试。 http://www.linuxwang.com/html/2150.html http://blog.csdn.net/feishicheng/article/details/70662094>如有问题&#xff0c;请联系我&#xff1a;easonjim#163.com&#xff0c;或者下方发表评论。<

C#中的类型转换

C# 出来也有些日子了&#xff0c;最近由于编程的需要&#xff0c;对 C# 的类型转换做了一些研究&#xff0c;其内容涉及 C# 的装箱/拆箱/别名、数值类型间相互转换、字符的 ASCII 码和 Unicode 码、数值字符串和数值之间的转换、字符串和字符数组/字节数组之间的转换、各种数值…

解构 StyleCLIP:文本驱动、按需设计,媲美人类 P 图师

来源 | HyperAI超神经&#xff08;ID:HyperAI&#xff09;作者 | 神经三羊StyleCLIP 是一种新型「P 图法」&#xff0c;它结合了 StyleGAN 和 CLIP&#xff0c;可以仅依据文本描述&#xff0c;对图像进行修改和处理。提起 StyleGAN 大家都不陌生。这个由 NVIDIA 发布的新型生成…

nexus 4 下 DualBootInstallation 安装 ubuntu touch

最近折腾ubuntu for phone ubuntu也算是雷声大雨点小&#xff0c;从edge手机开始&#xff0c;到说兼容一大部分谷歌机&#xff0c;到现在缩水说只适配nexus 4 节操掉了一地啊&#xff0c;对付这种情况&#xff0c;ubuntu touch也就可以只装着玩玩了&#xff0c;还好ubuntu 官方…

我的家庭私有云计划-13

嗯&#xff0c;昨天算由感而发啊&#xff0c;大家看看就好了。 嗯&#xff0c;接着说咱们的云。 先说啊&#xff0c;我没打算在这个领域里面完全自研&#xff0c;我还没那么疯&#xff0c;这个呢属于一体化解决方案&#xff0c;我认为还是社会分工合作的结果&#xff0c;不强调…

C语言return函数

return函数 说到return,有必要提及主函数的定义。很多人甚至市面上的一些书籍&#xff0c;都使用了void main( )这一形式 &#xff0c;其实这是错误的。 C/C 中从来没有定义过void main( ) 。C 之父 Bjarne Stroustrup 在他的主页上的 FAQ 中明确地写着&#xff1a; The defi…

怎样写出一个较好的高速排序程序

写出一个较好的高速排序程序 高速排序是经常使用的排序算法之中的一个&#xff0c;但要想写出一个又快又准的使用程序&#xff0c;就不是那么简单了须要注意的事项 首先要写正确。通常使用递归实现。其递归相当于二叉树展开&#xff0c;因此假设要用迭代实现的话须要使用一个队…

写代码时发现......还得是 SpringBoot !一篇拿下

关注了很多技术类公众号的读者肯定有这样一个感受&#xff0c;SpringBoot相关的文章铺天盖地&#xff0c;并且SpringBoot相关的文章阅读量、收藏量都很高&#xff0c;这也从侧面反映了SpringBoot技术的火爆。一切都在证明&#xff0c;SpringBoot已经成为了Java程序员必备的技能…

Python的 if .else.elif语句详解

If 语句 是用来判断的 Python 编程中 if 语句用于控制程序执行 用来检测一个条件&#xff1a;如果条件为 &#xff08;真&#xff09;true&#xff0c;就会运行这个语法块&#xff0c;如果为Fales 就跳过不执行。 elif是依附于if存在的&#xff0c;两者之间的运算逻辑相同&…

C#中string与byte[]的转换帮助类

在写C&#xff03;程序时&#xff0c;string和byte[]之间的转换比较烦&#xff0c;在移植一些老程序时感觉很不好。我在C&#xff03;中使用DES和TripleDES时移植一块老代码时也遇到了同样的情况。为了下次不为同样的事情烦恼&#xff0c;就写了下面的帮助类。 主要实现了以下…

鲲鹏入晋 万里腾飞,鲲鹏应用创新大赛2021山西赛区邀你来战!

2021 年 6 月 29 日&#xff0c;由山西省工业和信息化厅、山西转型综合改革示范区管理委员会为指导单位&#xff0c;华为技术有限公司主办&#xff0c;山西鲲鹏生态创新中心暨华为&#xff08;山西综改区&#xff09;DevCloud 创新中心承办&#xff0c;山西长河科技股份有限公司…

tcpdump-根据IP查看程序与服务都用了哪些端口

tcpdump -i em1 -tttt src 116.3.248.157 and port ! 6869 -nn -i 指定端口 -tttt 附带时间戳 -nn 解析域名与端口信息 ############################################# windows下可以使用netstat -nb |find “18999” 与 netstat -ao 结合使用&#xff0c;在通过pid号 查看进程…