Java创建类对象时对于构造器,静态对象、非静态对象的初始化有一定的顺序,我简单归纳一下:

class classes {public classes(String n) {System.out.println("classes constructor.   " + n);}
}class classOne {static classes class2 = new classes("class2");classOne() {System.out.println("classOne constructor");}classes class1 = new classes("class1");
}class classTwo extends classOne {classes class3 = new classes("class3");static classes class4 = new classes("class4");classTwo() {System.out.println("classTwo constructor");}
}public class Test4 extends classTwo {classes class5 = new classes("class5");static classes class6 = new classes("class6");Test4() {System.out.println("Test4  constructor");}public static void main(String[] args) {Test4 test4 = new Test4();}
}

在这个例子中,类classes是为了下面的类创建对象时能有一定的响应,因为在类中创建基本类型时无法在屏幕看到它被创建的消息,因此我使用了classes作为一个标记,当我创建了一个classes对象且在代码中调用时,会得到相应的响应。

classOne是一个基类,它里面包含了一个静态的classes对象,一个非静态的classes对象,一个构造器。calssTwo继承了classOne,同样地,它也有基类的相同类型的数据定义,为了降低两个类之间初始化顺序的偶然性,我加入了主类Test4继承了classTwo,以模拟多层次的继承关系。

现在,在Test4中的main方法中创建一个Test4对象,在屏幕上的输出如下:

classes constructor. class2
classes constructor. class4
classes constructor. class6
classes constructor. class1
classOne constructor
classes constructor. class3
classTwo constructor
classes constructor. class5

Test4  constructor

我简单解读Java对于这段代码初始化的顺序,首先,创建Test4对象指令发出后,Java查找到Test4还有基类ClassTwo,而classTwo还有基类calssOne,假如classOne还有基类(实际上classOne继承了Java中的Object类,这里不做讨论),它会一直查找,知道找到根本的那个类。找完(也可以称作类的加载)之后,开始执行初始化,首先初始化基类的static成员,即是创建class2这个对象的这段代码,接着是初始化基类的导出类中的static成员,这个初始化一直到最后层次的导出类,我们先称它为过程1。现在static成员被初始化完毕,接着再回到基类,也就是本例中的classOne这个类,初始化它的非static成员,然后调用它的构造器,请注意,这个过程一定是非static成员先于构造器,不管它们在代码中的顺序如何。调用完classOne构造器后,来到calssTwo,初始化它的非static成员,调用它的构造器,接着来到下一个导出类Test4,初始化它的非static成员,调用它的构造器,这样一层一层地执行这种指令,如果从classOne到Test4中间还有多个中间类,那么都会执行这种指令。

至此,一个Test4对象的构建就完成了,归纳起来大概就是:

基类static成员 > 导出类1static成员 > 导出类1的导出类static成员 > ..... > 基类非static成员 > 
基类构造器 > 导出类1非static成员 > 导出类1构造器 > 导出类1的导出类非static成员 > 导出类1的导出类构造器

> ....非static成员 > ....构造器 > 最底层导出类非static成员 > 最底层导出类构造器

此外,记得我刚才标注的过程1,即初始化static成员的这个过程。当我们第一次创建对象时,这个static成员的初始化过程才会发生,此后如果再次创建对象,过程1不再发生,比如我在Test4的main方法种创建完test4这个对象之后,在它后面再加一行代码:

Test4 test42 = new Test4();

那么针对这行的创建结果,响应就是:

classes constructor. class1
classOne constructor
classes constructor. class3
classTwo constructor
classes constructor. class5

Test4  constructor

也就是不再初始化static成员。

原因大概就是:static成员不属于某个具体的类对象,它属于整个类,因此,static成员的初始化只在类第一次加载时发生,对于本例中创建的test4对象,就是发生了类的第一次加载,因此它执行了初始化static,对于之后的test42对象,类不是第一次加载,因此不执行初始化static成员的指令。

以上代码在命令行以及JavaIDE eclipse中均测试一致。

Java构造器、静态对象、非静态对象等的初始化顺序相关推荐

  1. java中静态是什么,java中静态和非静态有什么区别

    首先我们先来说说jvm内存模型: jvm内存分为:方法区.堆.栈和程序计数器. 下面我们来简单的说说方法区.栈和堆: 方法区:是各个线程共享的区域,存放类信息/常量/静态变量: 栈:其实每个线程都会分 ...

  2. java 静态与非静态之间的访问规则简述

    java 静态与非静态之间的访问规则简述 1.静态与静态之间直接访问 2.非静态(实例级别)访问静态直接访问 3.静态访问非静态(实例级别),必须先创建对象再访问 package com.qfedu. ...

  3. java的静态与非静态 及其代码演示示例

    静态与非静态的概念 运行Java应用程序时,在实际的代码运行之前的一个步骤是加载类,具体点说,在Java SE 8的JVM中,需要先把类加载到Metaspace.如果类中有静态成员,加载类时会在hea ...

  4. 开发三年,java静态和非静态的这些弯弯绕绕你真的知道吗?

    问 Java 中,为什么不允许从静态方法中访问非静态变量? 了解特点 静态方法.属性:类加载时调用创建,通过类名直接调用,子类可继承不可重写 普通方法.属性:new对象时创建.注意new对象的时候 静 ...

  5. java 静态变量和非静态_Java中静态和非静态变量之间的区别

    变量为我们提供了程序可以操纵的命名存储.Java中的每个变量都有一个特定的类型,该类型确定变量的内存大小和布局.可以存储在该内存中的值的范围:以及可以应用于该变量的一组操作. 静态变量 静态变量也称为 ...

  6. C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态

    C#基础--类/接口/成员修饰符,多态.重载.重写,静态和非静态 类/接口/成员修饰符 C#修饰符---接口: 接口默认访问符是internal 接口的成员默认访问修饰符是public C#修饰符-- ...

  7. 第十七节:易混淆的概念(静态和非静态、拆箱和装箱)

    一. 静态和非静态 1. 概念介绍 ① 静态类(被static修饰) vs  普通类(没有被static修饰) ② 静态成员:被static修饰的成员,比如:静态方法.静态字段等 ③ 普通成员(实例成 ...

  8. C# 静态和非静态的区别

    静态标记 – static //静态方法 public static void Max(){ } //非静态方法 public void Max(){ }//静态类 public static cla ...

  9. C# 面向对象编程 1 面向对象类,静态和非静态的区别,构造函数,new关键字 ,析构函数

    C# 面向对象编程 1 文章目录 C# 面向对象编程 1 1.面向过程-----> 面向对象 2.类 3.静态和非静态的区别 4.构造函数 5.new关键字 6. 析构函数 1.面向过程---- ...

  10. 火山PC静态调用非静态

    1.一个编辑框,一个按钮 2.建立静态方法 3.建立一个类,放非静态方法 4.静态调用非静态 如需要在同一个类中直接静态调用非静态,等大佬,封装相关模块 5.演示 本文转载自利快云,原文地址:点击阅读 ...

最新文章

  1. java 枚举转byte_如何在java中将一个枚举转换为另一个枚举?
  2. 支持wince 系统的USB wifi 模组推荐
  3. python 单元测试_聊聊 Python 的单元测试框架(一):unittest
  4. 数据库--悲观锁【收藏,待尝试】
  5. 全球及中国临床试验支持服务行业十四五规模发展及应用前景调研报告2022-2027年
  6. linux 一些简记
  7. Python双版本下创建一个Scrapy(西瓜皮)项目
  8. 互联网 4 大发明之二维码,你如何使用 Python 生成二维码?
  9. golang PHP的区别,erlang和golang的区别
  10. git介绍和常用操作
  11. QT+OpenCV综合示例:图像混合(滑动条)
  12. 玩转 IntelliJ IDEA 2020
  13. C#LeetCode刷题之#747-至少是其他数字两倍的最大数( Largest Number At Least Twice of Others)
  14. 【clickhouse】clickhouse 行列转换 groupArray groupUniqArray 函数
  15. EditPlus配置Python环境
  16. 软件工程java向量相似度计算_向量的相似度计算常用方法9个
  17. 如何判断一个数为无符号数还是有符号数
  18. tl-wdr5620千兆版设置虚拟服务器,TL-WDR5620路由器如何设置 TL-WDR5620路由器上网设置步骤【介绍】...
  19. 闲谈IPv6-IPv6的分片(IPv6 Fragment)
  20. 简单局域网聊天室--Java版

热门文章

  1. 正则表达式 2. 单字符或
  2. 一、核心C#(第二部分)
  3. 好久没有深入研究技术了,最近这两年太忙但又不知道忙了些什么
  4. Entity Framework 学习高级篇1—改善EF代码的方法(上)
  5. 通用Login功能自动化测试
  6. INFO:InstallShield InstallScript工程中自定义界面文本输入控件的两个注意事项
  7. CUDA内存类型memory
  8. 凸优化问题工具包cvxpy安装
  9. 最长重复子串(Rabin-Karp算法)
  10. Temporal Segment Networks(TSN)实验及错误日志