本文对[#0x0001]、[#0x0008]、[#0x000B]做统一归纳。
一个类在能够被程序使用之前,必须经历三个准备工作(以下统称为类的执行):
-> 1. loading
-> 2. linking
--> 2.1 verification
--> 2.2 preparation
--> 2.3 resolution (optional)
-> 3. inintialization
在[#0x0008]、[#0x000B]中,我们使用的loading (加载),其实是统指了以上三个步骤。
loading指从.class文件中读取类的binary representation(即类的Class对象)的过程。
verfication过程验证binary representation的结构是否正确。
preparation过程为类的static field申请空间并赋默认值,同时为类的一些内部数据结构(如方法列表) 申请空间。
resolution过程分析类中的引用。resolution过程是一个optional的过程,在resolution过程中可以有不同的loading策略,比如说,在resolve class A的时候,发现class A中有一个class B的引用,此时可以立即加载class B,也可以do nothing。
initialization过程执行static initializer和initializer for static field (i.e. static variable initializer)。如:
private static int i = 5; //static variable initializer
//static initializer
static
{
......
}
以下不属于initialization阶段执行的代码:
private int i = StaticFunction(); //虽然涉及到了static方法,不过field不是static,不能算是static variable initialzer
//虽然是对static field初始化,但这个initializer本身不是static,依旧不能算是static initializer
{
StaticField = xxx;
......
}
由于loading和linking过程是implementation-dependent,且不方便追踪和查看,所以暂不讨论loading和linking的触发条件。以下着重讨论initialization。
initialization三原则:
-> 1. 触发原则:以下三种场景执行之前会触发initialization
--> 创建类的实例(constrcutor or Class.newInstance())
--> 调用类的static方法(包括constructor)
--> 非final的static field is used or assigned
-> 2. 父类原则:子类initialization之前,其direct父类必须initialization,and do it recursively. (p.s. 类实现的接口无需initialization,类实现的接口的父接口亦无需如此)
-> 3. 引发原则:如果子类initialization引发了父类的initialization,而此时父类还没有loading和linking,则父类的loading和linking也会被引发(p.s. 我觉得子类的initialization同样可以引发子类的loading和linking,如果loading和linking还没有执行的话)。
这里需要着重强调的是:loading、linking和initialization都是类的行为(class behavior) (所以initialization执行的都是static),而实例的创建(constructor or Class.newInstance())则是对象行为(object behavior)。
constructor执行的过程:
-> 执行this() or super()
-> 执行initializer和non-static variable initializer
-> 执行constructor的余下部分
回头看[#0x0008]的例子:
//@file Beetle.java
import static java.lang.System.out;
class Insect
{
private int i = 1;
protected int j;
private static int x1 = printInit("static Insect.x1 initialized");
Insect()
{
out.println("Insect constructor");
out.println("i = " + i + ", j = " + j + ", x1 = " + x1);
this.j = 2;
}
static int printInit(String s)
{
out.println(s);
return 3;
}
}
public class Beetle extends Insect
{
private int k = printInit("Beetle.k initialized");
private static int x2 = printInit("static Beetle.x2 initialized");
public Beetle()
{
out.println("Beetle constructor");
out.println("j = " + j + ", k = " + k + ", x2 = " + x2);
}
public static void main(String[] args)
{
Beetle b = new Beetle();
}
}
//output:
/*
static Insect.x1 initialized
static Beetle.x2 initialized
Insect constructor
i = 1, j = 0, x1 = 3
Beetle.k initialized
Beetle constructor
j = 2, k = 3, x2 = 3
*/
-> 访问Insect的main方法,是个static,引发Beetle的loading、linking和initialization,initialization又引发Insect的loading、linking和initialization
--> 执行Insect的initialization,private static int x1( = 3),打印"static Insect.x1 initialized"
--> 执行Beetle的initialization,private static int x2( = 3),打印"static Beetle.x2 initialized"
-> 进入main(),发现constructor
-> 隐式调用super(),转到Insect的constructor
--> Insect已经loading、linking和initialization了,直接执行non-static variable initializer,初始化private int i( = 1)和protected int j( = 0 by default)
--> 执行Insect constructor的余下部分,打印"Insect constructor"和"i = 1, j = 0, x1 = 3",然后j = 2
-> 执行Beetle的non-static variable initializer,初始化private int k( = 3),打印"Beetle.k initialized"
-> 执行Beetle constructor的余下部分,打印"Beetle constructor"和"j = 2, k = 3, x2 = 3"
回头看[#0x000B]的例子:
class Glyph
{
void draw()
{
System.out.println("Glyph.draw()");
}
Glyph()
{
System.out.println("Glyph constructor");
draw();
}
}
class RoundGlyph extends Glyph
{
private int radius = 1;
RoundGlyph(int r)
{
System.out.println("before assignment in constructor, radius = " + radius);
radius = r;
System.out.println("RoundGlyph constructor, radius = " + radius);
}
void draw()
{
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors
{
public static void main(String[] args)
{
new RoundGlyph(5);
}
}
//Output:
/*
Glyph constructor
RoundGlyph.draw(), radius = 0
before assignment in constructor, radius = 1
RoundGlyph constructor, radius = 5
*/
-> 访问PolyConstructors的main方法,loading、linking PolyConstructors,进入main,发现RoundGlyph构造器
-> 隐式调用super(),打印"Glyph constructor",执行RoundGlyph的draw()方法,打印"RoundGlyph.draw(), radius = 0" (此时还没有执行到RoundGlyph的non-static variable initializer)
-> 执行RoundGlyph的non-static variable initializer,radius = 1
-> 执行RoundGlyph构造器的余下部分,打印"before assignment in constructor, radius = 1",然后radius = 5,打印"RoundGlyph constructor, radius = 5"
分享到:
相关推荐
- **Mixed-Type Expressions**: Discussion of type conversions that occur when performing arithmetic operations involving different data types. - **Common Bugs with = and ==**: Explanation of common ...
Collaboration skills are crucial in team-based projects, especially those involving cross-functional teams where effective communication and cooperation are essential. ### Knowledge Point 5: ...
**Problem Statement:** Which of the following best models an arrow shot from point \(p\) to point \(q\) such that there is one and only one point in its flight where the arrow is parallel to the line ...
The document "Introduction_to_Optimum_Design.pdf" delves deeply into the principles and methods of optimum design, which is a critical area within engineering and applied mathematics. This field ...
Based on the provided information from the file "Addison.Wesley.C++.by.Dissection.2002.pdf," we can derive a comprehensive overview of the C++ programming language as covered in this text. The book is...
This example illustrates the use of switch statements in MATLAB for calendar calculations, which can be applied in various engineering contexts involving date and time manipulations. - **4.9–1 A ...
- **Simulation Time:** 0 to 80 ms (400 MagNet time steps). - **Total Solve Time:** 12 minutes. - **Average Number of Elements in MagNet:** 4,440. - **Average Number of Unknowns in MagNet:** 2,300. - *...
#### 例句1:“When asked about the ongoing uproar involving U.S. President Bill Clinton…” - **知识点解析**: - **句式结构**:使用“When + 过去分词”引导的时间状语从句,这是一种高级的英语句式,能够...
To address these concerns, a combination of JWTs and server-side session management techniques, such as those involving high-performance databases, may be more appropriate for certain applications.
The properties of correlation matrices, the conditions for nonsingularity and positive definiteness, and the methods for solving matrix equations are crucial for further exploration into the field of ...
### C Programming #### An Introduction to Computers ...- **The End of the File and Errors**: Discussion on how to handle end-of-file conditions and errors that may occur during file operations...
### WCF:分布式客户端/服务器游戏案例研究 #### 背景 Windows Communication Foundation(WCF)是由微软开发的一款软件开发工具包,作为.NET 3.0的一部分发布。它为跨机器之间的通信提供了一个灵活而强大的实现...
- **UDSs** enable the creation of additional scalar variables that can be transported or solved alongside the primary flow variables. These scalars can represent quantities like species concentration,...
For instance, phosphorylation of the N-terminal fragment of GSDMD can inhibit its pore-forming activity and thereby prevent pyroptosis. 5. **Involvement of Other Pathways**: The research also ...
It is structured to cater to the needs of students pursuing various engineering and scientific disciplines, where the use of C programming can range from being a supportive topic to a core component ...
- Specifying the structure of data for loading into SAP BW InfoProviders. #### TransferStructureList (RSTSFIELD) **Purpose:** This table contains detailed information about the fields within a ...
一类含p(x)-Laplacian的非齐次Neumann问题正解的多重性,范先令,邓绍高,我们研究如下形式含p(x)-Laplacian的非齐次Neumann边值问题正解的存在性和多重性: begin{equation*} left{ begin{array}{c} ...
#### 7.2 卡尔泰斯复数运算(Operations involving Cartesian Complex Numbers) 卡尔泰斯复数运算包括加减乘除等,是复数分析电路的基础。 #### 7.3 复数方程(Complex Equations) 复数方程在解决电路问题时提供...