【软件构造】-<笔记>-浅谈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 ...
随机推荐
- 数据库更新记录时,记录不存在则创建的sql语句
INSERT INTO 表名 (字段1(主键),字段2,字段3) values (#{value1},#{value2},#{value3}) ON DUPLICATE KEY UPDATE 字段2= ...
- C++之 类型定义语句--typedef
typedef的作用是给一个已经存在的数据类型起个别名. 使用的语法形式是:typedef 已有类型名 新类型名表;. 新类型名表中可以有多个标识符,它们之间用逗号分开,就是在一个typedef ...
- 单总线(1-Wire Bus)技术及其应用
单总线(1-Wire Bus)技术及其应用 reference: http://www.doc88.com/p-2106151016582.html 摘要:介绍了美DALLAS公司推出的单总线技术的原 ...
- java IO性能对比----read文件
本次对比内容为:(jdk1.8) fileInputStream:最基本的文件读取(带自己声明的缓冲区) dataInputStream:字节读取,在<java编程思想>一书中描述为使用最 ...
- 类 Arrays StringBuilder 跟 StringBuffer 的异同 SimpleDateFormat
类 String 同:起连接字符串类型作用 异: StringBuffer //线程安全 效率慢 StringBuilder //线程不安全 效率快 类 Arrays copyOf ( ...
- JavaScript 实时 全角转半角
//JavaScript全角字符转半角(参数str为input框输入的内容)var $fullChar2halfChar = function(str) { var result = ''; for ...
- NFS、FTP介绍
第二十五课 NFS.FTP介绍 目录 一. NFS介绍 二.NFS服务端安装配置 三.NFS配置选项 四.exportfs命令 五.NFS客户端问题 六.FTP介绍 七.使用vsftpd搭建ftp 八 ...
- .Net Core+Angular6 学习 第三部分(从api获取data)
. 现在开始需要集成angular6到VS项目中 1.1 打开Startup.cs文件, 在ConfigureServices方法中配置angular files的目录. 1.2 在Configure ...
- 第四次:渗透练习,xss学习
xss学习 一.学习目的 初步了解xss攻击,不包括(DOM类型) 二.附加说明 1.xss介绍 https://baike.baidu.com/item/XSS%E6%94%BB%E5%87%BB/ ...
- beifen
Comparison of Models for Predicting the Outcome of Craniocerebral Injury by Using Machine Learning ...