文档章节

Java继承与初始化全过程解析

断桥残雪断桥残雪
 断桥残雪断桥残雪
发布于 2015/08/12 18:45
字数 1205
阅读 2050
收藏 61

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

Java初始化简介

一般来说,在Java中,每个类产生的编译代码都存在于它自己的独立文件中,该文件只有在使用程序代码时才会被加载,也就是说,类的代码只有在初次使用时才加载。但是,如果存在static的话,就不一样了,当访问static字段或static方法时,也会发生加载。最常见的static方法是构造器方法了,虽然没有显示写明static关键字。所以,更准确地讲,Java的类应该是在其任何static成员被访问时加载的。

Java继承的概念

Java面向对象的三大特征是继承、封装、多态。继承的概念顾名思义,类似父子关系,子继承父亲。继承通常被认为是is-a关系,即子类是一个父累,可以这样理解。例如,大黄鸭是一个鸭子。虽然继承是面向对象的一个重大特性,但是对于项目的架构来说,继承应该慎用,常用的模式有组合,组合即一个类中持有另外一个类的对象,例如我们要构造一个汽车时,总要持有发动机、门、窗户、轮子等这些类的具体对象,显然汽车不是一个发动机,也不是一个轮子,它们的关系是has-a的关系,因此需要使用组合模式来设计。在OOP中,使用继承的一个优点是它可以向上转型(upcasting),即子类可以持有父类的方法,或者说子类是一个父类,通过向上转型,进而引出了多态的优点,即当有方法被覆盖时,父类类型的子类对象可以从子类依次向上查找,知道遇到该方法便可调用,这一优点为程序的可扩展性奠定了基础,如要新建一个子类,只用重新覆盖父类中已有的某个方法即可,在调用时即可实现多态的特性。然而,继承的使用场合应该尽量谨慎,使用前应该问问自己是否需要向上转型,如果后续业务中,必须要进行向上转型,那么就使用继承;否则,大可不必使用继承。

那么,在继承这种设计模式中,程序的加载过程是怎么进行的呢?父类的构造方法会不会加载?如果有static字段或方法,又是如何加载呢?

含有继承的程序加载过程

下面,我们以一个继承关系的两个类来探讨该问题,类中包含有static字段。

首先,写出基类的代码:


package demo0812.demo1;

public class SupClass {

		private int i=9;
		protected int j;
		public SupClass() {
			System.out.println("i="+i+",j="+j);
			j=39;
		}
		private static int x1=printInit("SupClass.x1 initialized");
		protected static int printInit(String str) {
			System.out.println(str);
			return 47;
		}
}
写出子类的代码:



package demo0812.demo1;

public class SubClass extends SupClass {

	private int k=printInit("SubClass.k initialized");
	public SubClass() {
		System.out.println("k="+k);
		System.out.println("j="+j);
	}
	
	private static int x2=printInit("SubClass.x2 initialized");
	public static void main(String[] args) {
		System.out.println("SubClass constructor");
		SubClass subClass = new SubClass();
	}
}
从上面的两个类代码可以看出,基类中含有一个static方法和一个static字段,另外还包含一个显示的构造方法。那么在程序执行过程中,当然先访问SubClass.main()方法,这是程序的入口,于是加载器开始启动并找出SubClass的编译代码(SubClass.class文件),然后,注意到该类有个关键字extends,说明它有个父类,于是,加载器便去加载父类的代码,即SupClass.class文件。加载器发现父类中含有一个静态字段,于是加载器先加载这个静态字段,同时也加载了静态方法,于是输出
SupClass.x1 initialized
,同时将x1的值赋为47。在加载完父类的静态区域以后,开始加载子类的静态区域,加载器于是看到,在子类中,也有一个静态字段x2,并且对它进行初始化,于是输出
SubClass.x2 initialized
,同时,将x2的值赋为47。这时,父类和子类的静态区都已经加载完成,于是,接着读取main函数,首先输出main中的第一行命令
SubClass constructor
接着,执行第二行命令,即对子类进行实例化,注意对子类实例化之前一定会对父类进行实例化,于是输出
i=9,j=0
接着,对子类进行按序执行,首先输出
SubClass.k initialized

并对k赋值为47,最后输出


k=47
j=39



这就是这段代码的总体的加载流程。





© 著作权归作者所有

断桥残雪断桥残雪
粉丝 53
博文 139
码字总数 94909
作品 0
广州
程序员
私信 提问
加载中

评论(1)

天天闹闹
天天闹闹
好清晰
从原理来理解继承关系的类初始化和实例化的顺序

就像之前的一个评论.我们学习的是思路. 很多人都知道继承关系的类的初始化和实例化的顺序,但如果忘记了怎么办? 如何找到自己的答案? 又如果遇到的问题是关于泛型的擦除问题,又该如何去分析?...

xpbug
2013/03/03
2.3K
4
好程序员Java分享JVM类加载机制

JVM相关概念 jdk<br>jdk(Java Development Kit)Java开发包,是Java开发人员用于编译和调试程序的一套程序的集合。 jre<br>jre(Java Runtime Evironment)Java运行时环境,是运行Java程序的...

好程序员IT
06/04
18
0
Java 类的生命周期详解

一、 引 言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内jav...

长平狐
2013/01/06
154
0
Java和Android ClassLoder对比以及Class加载过程

Java的ClassLoder的父子关系如下:Bootstrap--ExtClassClassLoader---AppClassLoader。 JVM启动时先运行启动类加载器Bottstrap,主要加载Java核心API;然后加载扩展类加载器ExtClassLoder,该...

JasmineBen
2018/05/23
0
0
Java类加载及变量初始化过程

Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就是解决上面3个问题的。 本文前...

kalo
2014/09/29
4.3K
0

没有更多内容

加载失败,请刷新页面

加载更多

是否有内置功能可以打印对象的所有当前属性和值?

所以我在这里寻找的是类似PHP的print_r函数。 这样一来,我可以通过查看问题对象的状态来调试脚本。 #1楼 可能值得一看- 是否有与Perl的Data :: Dumper等效的Python? 我的建议是 https://gi...

技术盛宴
19分钟前
5
0
直击面试,聊聊 GC 机制

前言 文章来源:https://studyidea.cn/ GC 中文直译垃圾回收,是一种回收内存空间避免内存泄漏的机制。当 JVM 内存紧张,通过执行 GC 有效回收内存,转而分配给新对象从而实现内存的再利用。 ...

程序通事
22分钟前
4
0
Mybatis where 1=1 和 标签

在mybatis中拼接查询语句,偶尔会出现where后面可能一个字段的值都没有,就导致所有条件无效,导致where没有存在的意义;但也有可能这些条件会存在。那解决这个问题的方法,最常见的就是: ...

观海562
24分钟前
4
0
git常用初始化设置

日志编辑工具 git config --global core.editor vim ssh访问 cd /home/weiguangyue/.sshssh-keygen -t rsa -C weiyue888999@126.com 提交者信息用户名 git config --global user.nam......

萧默
25分钟前
4
0
面试题-关于Java线程池一篇文章就够了

在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的。同时又鉴于公众号“程序新视界”的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将基于J...

程序新视界
29分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部