Java类中字段初始化过程详解

编程入门 行业动态 更新时间:2024-10-24 15:24:20

Java类中<a href=https://www.elefans.com/category/jswz/34/1771443.html style=字段初始化过程详解"/>

Java类中字段初始化过程详解

1. 初始化顺序

类中的变量定义顺序决定了初始化的顺序,即使分散到方法定义之间,变量定义仍然会在任何方法(包括构造器)调用之前就被初始化,看下面这段代码:

package com.yyj;public class OrderOfInitialization {public static void main(String[] args) {B b = new B();b.f();/** Initial class A with 1* Initial class A with 2* Initial class A with 3* Initial class B* Initial class A with 4* This is f()*/}
}class A {A(int value) {System.out.println("Initial class A with " + value);}
}class B {A a1 = new A(1);  // 在构造器之前定义B() {System.out.println("Initial class B");a3 = new A(4);  // 在构造器内定义}A a2 = new A(2);  // 在构造器之后定义void f() {System.out.println("This is f()");}A a3 = new A(3);  // 在尾部定义
}

在类 B 中,A 对象的定义分散到各个方法之间,但他们均在构造器执行前被初始化完成,其中有一个对象引用在构造器内被重新初始化。

a3 引用被初始化了两次:一次在构造器调用之前,另一次在构造器调用期间(第一个对象被丢弃了,因此稍后可能会被垃圾收集器回收)。

2. 静态数据的初始化

无论创建了多少对象,静态数据都只有一份存储空间。来看下面的代码:

package com.yyj;public class StaticInitialization {public static void main(String[] args) {System.out.println("Creating class B in main...");B b1 = new B();}static B b2 = new B();/** Initial class A with 2* Initial class A with 3* Initial class A with 1* Initial class B* This is A.f()* Creating class B in main...* Initial class A with 1* Initial class B* This is A.f()*/
}class A {A(int value) {System.out.println("Initial class A with " + value);}void f() {System.out.println("This is A.f()");}
}class B {A a1 = new A(1);static A a2 = new A(2);B() {System.out.println("Initial class B");a2.f();}static A a3 = new A(3);
}

静态字段 a2a3 的创建在 a1 字段之前,且仅在第一个 B 对象创建时被初始化,之后这些静态对象不会被重新初始化。

因此初始化的顺序是从静态字段开始,然后是非静态字段。例如要执行静态的 main 方法,必须先加载 StaticInitialization 类,然后初始化他的静态字段 b2,这就导致类 B 被加载,而类 B 中包含静态的类 A 的对象,因此 A 也被加载,所以这个程序中所有的类都在 main 方法开始执行前被加载。

现在总结一下对象创建的过程,假设有一个名为 A 的类:

  1. 尽管没有显式使用 static 关键字,但构造器实际上也是静态方法。因此,第一次创建类型为 A 的对象时,或者第一次访问类 A 的静态方法或静态字段时,Java 解释器会搜索类路径来定位 A.class 文件。
  2. A.class 被加载后(这将创建一个 Class 对象),它的所有静态初始化工作都会执行。因此,静态初始化只在 Class 对象首次加载时发生一次。
  3. 当使用 new A() 创建对象时,构建过程首先会在堆上为 A 对象分配足够的存储空间。
  4. 这块存储空间会被淸空,然后自动将该 A 对象中的所有基本类型设置为其默认值(数值类型的默认值是0,booleanchar 则是和0等价的对应值),而引用会被设置为 null
  5. 执行所有出现在字段定义处的初始化操作。
  6. 执行构造器。这实际上可能涉及相当多的动作,尤其是在涉及继承时。

3. 显式的静态初始化

Java 允许在一个类里将多个静态初始化语句放在一个特殊的“静态子句”里(有时称为静态块):

package com.yyj;public class ExplicitStatic {public static void main(String[] args) {System.out.println("Inside main()");B.a1.f();/** Inside main()* Initial class A with 1* Initial class A with 2* This is A.f()*/}
}class A {A(int value) {System.out.println("Initial class A with " + value);}void f() {System.out.println("This is A.f()");}
}class B {static A a1;static A a2;static {a1 = new A(1);a2 = new A(2);}B() {System.out.println("Initial class B");}
}

尽管看起来有点像一个方法,但它只是在 static 关键字后加了一段代码,这段代码和其他静态初始化语句一样,只执行一次:第一次创建该类的对象时,或第一次访问该类的静态成员时(即使从未创建过该类的对象)。

更多推荐

Java类中字段初始化过程详解

本文发布于:2023-12-05 02:47:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1662824.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字段   初始化   详解   类中   过程

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!