Java中的类初始化和实例初始化

我也是小白,各位倘若看到一定要带思考的去看。

一、背景

存在类Father和类Son,其中类Son继承了Father类。

1.父类: Father

/** * @Author Yiang37 * @Date 2020/4/9 23:44 * Description: */ public class Father { private final int i = test(); private static final int j = method(); static { System.out.print("(1)"); } { System.out.print("(3)"); } Father() { System.out.print("(2)"); } public int test() { System.out.print("(4)"); return 1; } public static int method() { System.out.print("(5)"); return 1; } }

2.子类: Son

package cn.yang37.classloading.loadstep; /** * @Author Yiang37 * @Date 2020/4/9 23:44 * Description: */ public class Son extends Father { private final int i = test(); private static final int j = method(); static { System.out.print("(6)"); } { System.out.print("(8)"); } Son() { System.out.print("(7)"); } @Override public int test() { System.out.print("(9)"); return 1; } public static int method() { System.out.print("(10)"); return 1; } public static void main(String[] args) { // Son s1 = new Son(); // System.out.println(); // Son s2 = new Son(); } }

二、初始化

初始化包括?

成员变量赋初值、代码块、构造器

注意方法是被调用的,有人调用它它才执行相应的东西。

三、类初始化

在一开始,注释掉son类main方法中代码

public static void main(String[] args) { // Son s1 = new Son(); // System.out.println(); // Son s2 = new Son(); }

执行结果如下:

(5)(1)(10)(6)

1.规则

1.1 实例初始化之前先要进行类的初始化(加载类),即执行一些static相关的操作.

所以你执行空的main()也会输出结果,因为在进行类的初始化.

1.2 子类初始化要先初始化其父类

即先执行的Father的,再执行Son的.

1.3 类初始化即是执行clinit(ClassInit)方法

  • 加载静态变量/静态代码块
  • 按顺序加载(上到下的顺序执行)
  • 这个clinit方法只执行一次,即类只初始化一次即可.

2.扩展

2.1 将父类中的static代码块放到静态变量之前,可以看到结果按顺序改变。

package cn.yang37.classloading.loadstep; /** * @Author Yiang37 * @Date 2020/4/9 23:44 * Description: */ public class Father { private final int i = test(); static { System.out.print("(1)"); } private static final int j = method(); { System.out.print("(3)"); } Father() { System.out.print("(2)"); } public int test() { System.out.print("(4)"); return 1; } public static int method() { System.out.print("(5)"); return 1; } }

先输出1再输出5,即按顺序加载.

(1)(5)(10)(6)

四、实例初始化

取消Son类中main方法的第一句注释,即:

进行new操作,即实例的初始化.

public static void main(String[] args) { Son s1 = new Son(); // System.out.println(); // Son s2 = new Son(); }

此时将会先进行类初始化,再进行实例初始化,结果如下。

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)

1.规则

1.1 实例初始化即是执行init方法

Java文件在编译后会在字节码文件中生成init方法,该方法被称之为实例构造器。init方法是在对象实例化时执行的。

1.2 方法中调用几个构造器就执行几个init方法,每次创建对象都会执行相应的init方法。

1.3 init方法由非静态实例变量显式赋值、非静态代码块和相应的构造器组成。

1.4 非静态实例变量赋值与非静态代码块按上到下的顺序执行,构造器在最后执行。

构造器嘛,要用到变量之类的,肯定最后阶段啦.

1.5 init方法的首行是super()或者带参数的super(),即父类init方法。

2.扩展

2.1 父类中的test()方法输出的是(4),为何父类中结果为932?

非静态方法前有一个默认的对象this

this在构造器(或者init方法)表示的是正在创建的对象。

这里是在创建Son类的对象,所以执行的是重写后的代码。

2.1 取消main中的所有注释

public static void main(String[] args) { Son s1 = new Son(); System.out.println(); Son s2 = new Son(); }

运行结果:

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7) (9)(3)(2)(9)(8)(7)

可以看到(9)(3)(2)(9)(8)(7)执行了两次,因为new Son()执行了两次.

五、总结

初始化操作包括成员变量、静态/非静态代码块和构造器。

1.先类初始化,再实例初始化。

2.都是先父类再子类。

3.类初始化关键词"静态"。

4.实例初始化关键词"非静态",构造器在最后。

5.注意构造器和实例初始化init方法中的this对象。

六、补充

1.哪些方法不能被重写?

final方法
静态方法
private等子类中不可见方法

2.多态性的体现?

子类若重写了父类的方法,则通过子类对象调用的一定是子类重写过的方法
非静态方法默认的调用对象是this
this对象在构造器或者init方法中就是正在创建的对象


__EOF__

本文作者羊37
本文链接https://www.cnblogs.com/yang37/p/12676668.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   羊37  阅读(914)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示