【软件构造】-<笔记>-浅谈java中类的初始化过程
编写java程序时,每创建一个新的对象,都会对对象的内容进行初始化。
每一个类的方法中的局部变量都有严格的初始化要求,因此假如写出下面的程序:
void f(){
int i;
i++;
}
编译时就会得到一条出错信息,因为java会严格检查方法内部局部变量的初始化,正如《java编程思想》中所说“未初始化的局部变量更有可能是程序员的疏忽”
但是对于类内部的字段,java并不会严格检查字段是否初始化,因为类的每一个基本数据类型成员都保证会有一个初始值,哪怕构造器什么都没做。
其实一个对象的初始化并不仅仅只是简单的调用构造器,在这之前,java已经做了很多工作了。
创建一个新的对象,就相当于苹果树上长出了一个新的苹果。只有在这个苹果长出来的时候,我们才知道其具体的形状,颜色,重量,这是每个苹果所具有的特性,这些特性就相当于对象中的字段。但是所有的苹果同样具有共性,比如说都具有类似的结构,这些性质就相当于对象中的static字段,是所有该类对象所共享的。而构造器,就相当于在采摘下苹果之后,通过人工的手段对其特性做出一些改变。
当java要创建一个新的对象时,首先会查找类路径,找到对应的类,相当于我们种下了一颗苹果树。
此时java会载入这个类,此时类中有关静态初始化的所有动作都会被执行,即类中带有static前缀的字段会被分配内存,然后进行初始化的赋值。无论为这个类new多少个对象,static字段的初始化在整个程序的生命周期中只会进行一次,且有自己独立的内存位置,为所有该类的对象所共享。就像我们知道这棵种下的苹果树会长出的东西叫做苹果,和世界任何一个地方的同类的苹果树一样,虽然苹果还没有长出来,但是它作为苹果所具有的性质是客观存在的。
//例子
如果当前类是导出类,那么java编译器就会从其基类开始加载,分别初始化其中的静态域;
无论如何,static域的初始化都只会进行这一次。
接下来,java编译器就会为该具体的对象分配内存空间。内存被分配的时候,对应的内存空间会被全部清0,所以所有的非static字段的初始值都是0或者与0等价的值,对象的引用都被置为null。这就相当于苹果树的果实刚刚准备生长的状态,一切都是最初的模样。
下一步,java编译器就会利用每个字段的初始化语句对字段进行赋值,如果初始化语句调用了别的对象或者方法,那么编译器也会不知疲倦的去找,就是为了保证在调用构造器之前,字段的初始化语句都执行完成。值得注意的是,类中字段的分配内存空间与赋值的过程是先于构造器以及其他方法进行的,与代码中初始化语句与方法的排列顺序无关,哪怕包括构造器在内的所有方法都排在字段初始化语句之前,编译器也会跳过这些方法,先执行初始化语句。
如果当前类是导出类,那么java编译器就会从其基类开始执行字段的初始化,逐步向外进行,导出类的加载与初始化赋值都必须在基类的基础上进行,不能凭空产生。
这个赋值的过程就相当于苹果树的果实的生长过程,苹果的大小,重量,颜色等特性都是在这个过程中慢慢形成的。
接下来才轮到构造器对对象进行初始化,按照new对象时输入的参数对每个对象进行塑造,这个过程就相当于苹果采摘完成之后,清洗干净,修剪枝叶。
测试代码如下:
public class init_Test {
public static void main(String args[]) {
System.out.println("the first code in main");
}
static apple apple1=new apple();
static apple apple2=new apple();
} class Test{
static int f(String words) {
System.out.println(words);
return 1;
}
} class apple{
int value1 =Test.f("init value1");
static int static1=Test.f("static init static1");
apple(){
System.out.println("constructor of class apple");
System.out.println("check static1 ="+static1);
System.out.println("check static2 ="+static2);
System.out.println("check static3 ="+static3);
System.out.println("check value1 ="+value1);
System.out.println("check value2 ="+value2);
System.out.println("check value3 ="+value3);
}
int value2=Test.f("init value2");
static int static2=Test.f("static init static2");
static int static3;
int value3;
}
产生的输出如下:
static init static1
static init static2
init value1
init value2
constructor of class apple
check static1 =1
check static2 =1
check static3 =0
check value1 =1
check value2 =1
check value3 =0
init value1
init value2
constructor of class apple
check static1 =1
check static2 =1
check static3 =0
check value1 =1
check value2 =1
check value3 =0
the first code in main
接下来让我们捋清楚这段代码的执行过程。
首先进入程序的入口:main方法
要执行main方法,就需要首先加载main方法所在的init_Test类。
加载时会对static域进行初始化,因此控制流会跳过main方法,首先执行下面的两条初始化语句,对静态的apple1和apple2进行初始化。也就是创建两个新的apple对象。
初始化调用了apple方法,因此控制流会转而寻找apple类,这是控制流第一次到达该类,于是就会对其中的静态域进行初始化:
也就是上图所示的static1,static2,static3三个变量。
初始化调用了以下静态方法,定义该方法的目的就是在控制台中打印信息。
注意到控制台中的前两条输出:
===============================================================
完成了类的加载,就开始创建具体的对象了,此时控制流开始为apple1对象创建内存空间,非static域首先被赋值为0,然后执行对应的初始化语句;
执行完之后,终于进入构造器,执行构造器内的初始化语句;
控制台产生如下输出:
然后执行构造其中的剩下语句,将apple1中的各个字段的值打印出来:
其中的static3与value3没有指定初始值,因此默认为0;
会到main方法,终于完成了apple1对象的创建,开始执行apple2的创建:
控制台中的输出:
最后,终于执行到了main方法的第一条语句,实属不易:
通过上述例子,可以对java中的初始化过程做出一个总结:
构造器的构造过程涉及更复杂的知识,本菜鸡还没有学到,等后面学习了相应的知识再进行补充;
由于刚刚接触java,文章中错误不少,求看官大佬指正;
【软件构造】-<笔记>-浅谈java中类的初始化过程的更多相关文章
- 浅谈Java中静态初始化块跟非初始化块
众所周知在JAVA编程语言中有两种初始化块: 静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别 静态初始化块 定义: ...
- 浅谈Java中的初始化和清理
引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...
- Java 中类的初始化过程
先来一张 JVM 中的内存模型 . 在Java 虚拟机原理这本书中介绍了类会被初始化的 5 种情况 . 1 遇到 new getstatic putstatic 和 invokestatic 这 4 ...
- 浅谈Java变量的初始化顺序详解
规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器证明代码: 复制代码 代码如下: p ...
- !! 浅谈Java学习方法和后期面试技巧
浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...
- 浅谈JAVA集合框架
浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...
- 浅谈java类集框架和数据结构(2)
继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...
- 浅谈Java中的栈和堆
人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数 ...
- 龙生九子-浅谈Java的继承
龙生九子-浅谈Java的继承 书接上回,我们之前谈过了类和对象的概念,今天我来讲一讲面向对象程序设计的另外一个基本概念-继承 目录 为什么需要继承 自动转型与强制转型 继承能干啥 复写和隐藏 supe ...
随机推荐
- 小白的首个maven web项目Step1软件安装一(jdk的下载配置和eclipse的安装)
因为电脑太卡加了一个固态硬盘导致系统重装, 把之前的C盘和D盘合并成一个盘,这下之前下的杂七杂八的软件应该差不多都清干净了. 申请这个博客是想记录最近写项目学习的一些事,系统重装之后,发现自己都已经忘 ...
- Java作业:第四次过程性考核 ——长春职业技术学院 16级网络工程
Java作业:第四次过程性考核 码云链接:https://gitee.com/SoridoD/java_kaohe4 (时间匆忙没打注释,真有急事) (客户端和服务器会自动创建表,所以没有sql ...
- .NET--------未能加载文件或程序集“System.Net.Http.Formatting”或它的某一个依赖项。
未能加载文件或程序集“System.Net.Http.Formatting”或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) 解决方 ...
- MongoDB基本命令总结
其实一直想整理下我常使用的MongoDB数据库的一些操作命令,终于有时间了~ MongoDB是一种开源的,免费的非关系型数据库(NoSql),不存在表.记录等概念,与通常的关系型数据库有些差异: Mo ...
- Java容器解析系列(8) Comparable Comparator
Comparable和Comparator接口是两个用于对对象进行大小比较的接口,在java集合相关类中,也被经常地使用到. 关于其使用,可以参考网络上的其他博客(没什么好说的);这里阐述关于这两个接 ...
- pseudo-class与pseudo-element的不同点与相同点
关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...
- SQLZOO网页中SQL的答案(SELECT from nobel篇)
SELECT from nobel篇 1. 更改查詢以顯示1950年諾貝爾獎的獎項資料. 答案: SELECT yr, subject, winner FROM nobel WHERE yr = 19 ...
- python基础(数组)
列表 也叫list 列表 数组 stus = ['明明','莉莉','亮亮'] 新增元素: Append,insert Append 在列表末尾加一个元素 Insert()在指定位置上增加一个元素 删 ...
- Vmware Vsan 部署中如何将非SSD 硬盘标识为SSD
通过SSH 登录ESXi主机 # esxcli storage nmp device list #查询ESXI 发现的存储设备 # esxcli storage nmp satp rule add ...
- Django中Model-Form验证
Django中Model-Form验证 class UserType(models.Model): caption=models.CharField(max_length=32) class User ...