编写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中类的初始化过程的更多相关文章

  1. 浅谈Java中静态初始化块跟非初始化块

    众所周知在JAVA编程语言中有两种初始化块:   静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别   静态初始化块 定义:       ...

  2. 浅谈Java中的初始化和清理

    引言 这篇文章我们主要介绍Java初始化和清理的相关内容,这些内容虽然比较基础,但是还是在这边做一个简单的总结,方便以后查阅. 初始化过程 Java尽力保证:所有变量在使用之前都会得到恰当的初始化(对 ...

  3. Java 中类的初始化过程

    先来一张 JVM 中的内存模型 . 在Java 虚拟机原理这本书中介绍了类会被初始化的 5 种情况 . 1 遇到 new getstatic putstatic 和 invokestatic 这 4 ...

  4. 浅谈Java变量的初始化顺序详解

    规则1(无继承情况下):对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器证明代码: 复制代码 代码如下: p ...

  5. !! 浅谈Java学习方法和后期面试技巧

    浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...

  6. 浅谈JAVA集合框架

    浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...

  7. 浅谈java类集框架和数据结构(2)

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

  8. 浅谈Java中的栈和堆

    人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数 ...

  9. 龙生九子-浅谈Java的继承

    龙生九子-浅谈Java的继承 书接上回,我们之前谈过了类和对象的概念,今天我来讲一讲面向对象程序设计的另外一个基本概念-继承 目录 为什么需要继承 自动转型与强制转型 继承能干啥 复写和隐藏 supe ...

随机推荐

  1. react-redux-数据流

    redux是严格的单向数据流 1,store.dispatch(action) 2, reducer(previousState, action), reducer是纯函数.它仅仅用于计算下一个 st ...

  2. 关于python中的GIL

    什么是GIL锁? GIL是Global Interpreter Lock的缩写,GIL中文可以称为全局解释器锁.提及到GIL,我们要知道它是在实现Python解析器(CPython)时所引入的一个概念 ...

  3. [Leetcode 40]组合数和II Combination Sum II

    [题目] Given a collection of candidate numbers (candidates) and a target number (target), find all uni ...

  4. shell脚本中给字符串添加颜色

    shell脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e 格式如下: echo -e "\033[字背景颜色:文字颜色m字符串\033[0m" 例如: ec ...

  5. JQuery案例一:实现表格隔行换色

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. volatile 与 JVM 指令重排序

    前言: 在做单例模式时 有博客在评论区 推荐使用 volatile 关键字 进行修饰 然后用了两天时间查资料看文档 发现涉及的面太广 虽然已经了解为什么要使用 volatile + synchroni ...

  7. ecplise中设置字符编码

    ecplise 设置 1 ecplise编码格式 右键 在general-workspace- text file encoding 选择utf-8 2 jsp文件编码格式 web-jspfile-e ...

  8. "HTML编码规范" 笔记

    转自学习网站(百度原创):https://github.com/ecomfe/spec/blob/master/html-style-guide.md 本文是百度培训网站上关于HTML编码规范的笔记, ...

  9. 对于一个段错误(核心已转储)问题的解答,错误的英文翻译是segment fault(core dumped)

    笔者在学习ROS的时候遇到的这个问题,使用的系统是ubuntu16.04,ROS版本是kinetic,在运行小海龟程序的时候突然打不开海龟界面的程序节点turtlesim-node,四处寻找答案未果, ...

  10. 学习Spring

    一.Spring 概述 1.概述   Spring 框架是一个开源的 Java 平台,它最初是由 Rod Johnson 编写的,并且于 2003 年 6 月首次在 Apache 2.0 许可下发布. ...