Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造方法)

1、执行顺序

1.1、一个类中的初始化顺序

(静态变量、静态初始化块)=>(变量、初始化块、构造器)。

1.2、两个具有继承关系类的初始化顺序

父类的(静态变量、静态初始化块)=> 子类的(静态变量、静态初始化块)=> 父类的(变量、初始化块、构造器)=> 子类的(变量、初始化块、构造器)。

示例如下:(结果见注释)

 1 class A {
 2     public A() {
 3         System.out.println("Constructor A.");
 4     }
 5
 6     {
 7         System.out.println("Instance Block A.");
 8     }
 9     static {
10         System.out.println("Static Block A.");
11     }
12
13     public static void main(String[] args) {
14         new A();/*
15                  * Static Block A. Instance Block A. Constructor A.
16                  */
17     }
18 }
19
20 class B extends A {
21     public B() {
22         System.out.println("Constructor B.");
23     }
24
25     {
26         System.out.println("Instance Block B.");
27     }
28     static {
29         System.out.println("Static Block B.");
30     }
31
32     public static void main(String[] args) {
33         new A();/*
34                  * Static Block A. Static Block B. Instance Block A. Constructor A.
35                  */
36         System.out.println();
37         new B();/*
38                  * Instance Block A. Constructor A. Instance Block B. Constructor B.
39                  */// 静态成员和静态初始化块只会执行一次。
40     }
41 }

2、对变量值的影响

2.1、问题

Java中一个变量的初始化与初始化块对该变量的赋值同时存在时变量的最终值如何确定?特别是初始化块在变量定义之前甚至静态初始化块和实例初始化块都对该变量进行赋值时更迷惑人。如对于如下示例,输出的值分别为多少?(已给出):

 1 class C {
 2
 3     static {
 4         a = 2;
 5         b = 2;
 6     }
 7     static int a;
 8     static int b = 1;
 9
10     public C() {
11         e = 3;
12     }
13
14     {
15         c = 2;
16         d = 2;
17         e = 2;
18     }
19     int c;
20     int d = 1;
21     int e = 1;
22
23     public static void main(String[] args) {
24         System.out.println(C.a);//2
25         System.out.println(C.b);//1
26         System.out.println(new C().c);//2
27         System.out.println(new C().d);//1
28         System.out.println(new C().e);//3
29     }

2.2、分析

成员变量(类变量、实例变量)的 初始化块赋值 及 变量定义 同时存在时变量的值的确定。包含如下几种情况:

情况1、静态变量定义 及 静态初始化块改变该变量值 同时存在时变量的最终值。

情况2、实例变量定义 及 实例初始化块改变该变量 同时存在时变量的最终值。

情况3、或上述两种同时改变一个变量 时变量的最终值。

若初始化块在变量定义之后,则易知值为初始化块里的赋值,因此这里考虑若初始化块在变量定义之前的情形

2.3、结论

(考虑 对变量赋值的初始化块在变量定义之前 的情形)

1、对于静态操作和实例操作同时存在的情况(情况3),根据上节所述的执行顺序确定值;

2、若定义变量时未显式初始化,则成员变量会被默认初始化,进一步地若存在初始化块则变量的值为初始化块的赋值。如:

 1 class C {
 2     public C() {
 3     }
 4
 5     {
 6         a = 3;
 7     }
 8     static {
 9         a = 2;
10     }
11     static int a;
12     static int b;
13
14     public static void main(String[] args) {
15         System.out.println(C.a);// 2
16         System.out.println(new C().a);// 3
17         System.out.println(C.b);// 0
18     }
19 }

3、若定义时显示地初始化了,即情况1、2,其处理方法一样:

变量定义时进行显式初始化实际上内部隐含 定义及初始化块对之进行赋值 两个过程,因此若还包含初始化块代码,则Java会将它们合并成一个处理,所以结论是显式初始化和初始化块哪个在后值就是哪个。如:

 1 class C {
 2     // 以下关于静态初始化的
 3     static {
 4         a = 2;
 5     }
 6     static int a = 1;
 7     static int b = 1;
 8     static {
 9         b = 2;
10         c = 2;
11     }
12     static int c;
13
14     {
15         d = 2;
16     }
17     int d = 1;
18     int e = 1;
19     {
20         e = 2;
21         f = 2;
22     }
23     int f;
24
25     public static void main(String[] args) {
26         System.out.println(C.a);// 1
27         System.out.println(C.b);// 2
28         System.out.println(new C().c);// 2
29         System.out.println(new C().d);// 1
30         System.out.println(new C().e);// 2
31         System.out.println(new C().f);// 2
32     }
33 }
时间: 2024-10-16 09:33:24

Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造方法)的相关文章

java 子类、父类中静态代码块、字段,非静态代码块、字段以及构造函数的初始化顺序和次数

一个类中的数据初始化顺序是面试官非常喜欢出的面试题之一,本文用一个实例来介绍java中子类.父类中静态代码块.字段,非静态代码块.字段以及构造函数的执行顺序和次数. 一.包结构 Cat继承Animal Runner里包含main函数,程序入口 Sing类主要用来打印执行顺序的序列号 二.代码 public class Animal { Sing s1=new Sing(1,"animal\tnot static field"); static Sing s2=new Sing(2,&q

Java 类成员的初始化顺序

Java 类成员的初始化顺序 前言:开发中碰到一个Java文件中有很多的成员变量,包括静态和非静态的,还有很多的初始化方法,很好奇这些成员的初始化顺序,在这里作个研究. ? 1 ?无继承情况下的Java初始化顺序: class Sample { Sample(String s) { System.out.println(s); } Sample() { System.out.println("Sample默认构造函数被调用"); } } class Test { static Samp

Android(java)学习笔记136:Java类初始化顺序

Java类中初试化的顺序: 由此得出Java普通类初始化顺序结论: 静态变量 静态初始化块 变量 初始化块 构造器 由此得出Java继承类初始化顺序结论: 1 .继承体系的所有静态成员初始化(先父类,后子类) 2 .父类初始化完成(普通成员的初始化-->构造函数的调用) 3 .子类初始化(普通成员-->构造函数) Java初始化顺序如图: 代码演示: class Sample { Sample(String s) { System.out.println(s); } Sample() { Sy

Java 对象初始化顺序 执行顺序

先看一道Java面试题: 求这段程序的输出. 解答此题关键在于理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题: 从程序的执行顺序去解答: 1.编译:当这个类被编译通知后,会在相应的目录下生成两个.class 文件.一个是 Base.class,另外一个就是Base$Sub.class.这个时候类加载器将这两个.class  文件加载到内存 2.Base base= new Sub(): 声明父类变量base对子类的引用,JAVA类加载器将Base,Sub类加载到JVM(Java虚拟

Java初始化顺序(转)

Java初始化顺序 1  无继承情况下的Java初始化顺序: class Sample { Sample(String s) { System.out.println(s); } Sample() { System.out.println("Sample默认构造函数被调用"); } } class Test{ static Sample sam=new Sample("静态成员sam初始化"); Sample sam1=new Sample("sam1成员

Java&&初始化顺序总结

1  无继承情况下的Java初始化顺序: class Sample { Sample(String s) { System.out.println(s); } Sample() { System.out.println("Sample默认构造函数被调用"); } } class Test{ static Sample sam=new Sample("静态成员sam初始化"); Sample sam1=new Sample("sam1成员初始化")

C++——类继承以及类初始化顺序

对于类以及类继承, 几个主要的问题:1) 继承方式: public/protected/private继承. 这是c++搞的, 实际上继承方式是一种允许子类控制的思想. 子类通过public继承, 可以把基类真实还原, 而private继承则完全把基类屏蔽掉. 这种屏蔽是相对于对象层而言的, 就是说子类的对象完全看不到基类的方法, 如果继承方式是private的话, 即使方法在基类中为public的方法. 但继承方式并不影响垂直方向的访问特性, 那就是子类的函数对基类的成员访问是不受继承方式的影

C++成员初始化顺序

#include <iostream> using namespace std; int seti() {cout << "seti" << endl;return 1;} int setj() {cout << "setj" << endl;return 1;} class a { public: a() {cout << "a()~~~~~" << endl;

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)(转)

大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果.这实际上是在考查我们对于继承情况下类的初始化顺序的了解. 我们大家都知道,对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序以此是(静态变量.静态初始化块)>(变量.初始化块)>构造器.我们也可以通过下面的测试代码来验证这一点: Java代码 p