Java中的实例控制流
本文将解释每当创建对象时实例控制流是如何发生的。
普通类中的实例控制流程
每当我们执行Java .class 文件时,都会执行第一个静态控制流。在静态控制流中,如果我们正在创建一个对象,以下步骤序列将作为实例控制流的一部分执行:
- 从上到下标识实例成员。
- 从上到下执行实例变量赋值和实例块。
- 构造函数的执行。
例子:
Java
// InstanceControlFlow class
class InstanceControlFlow {
// initializing instance integer i = 10
int i = 10;
// first instance block
{
// call instance method (methodeOne())
methodOne();
System.out.println("First Instance Block");
}
// constructor
InstanceControlFlow()
{
System.out.println("Constructor");
}
// main method
public static void main(String[] args)
{
// create InstanceControlFlow class object
InstanceControlFlow f = new InstanceControlFlow();
System.out.println("Main method");
}
// instance method (methodOne())
public void methodOne() { System.out.println(j); }
// second instance block
{
System.out.println("Second Instance Block");
}
// initializing instance integer j = 20
int j = 20;
}
Java
// Parent class
class Parent {
// initializing instance integer x = 10
int x = 10;
// first instance block of Parent class
{
// call instance method (methodeOne())
methodOne();
System.out.println("Parent First Instance Block");
}
// constructor of Parent class
Parent()
{
System.out.println("Parent Class Constructor");
}
// main method of Parent class
public static void main(String[] args)
{
// create Parent class object
Parent p = new Parent();
System.out.println("Parent Class Main Method");
}
// instance method (methodOne())
public void methodOne() { System.out.println(y); }
// initializing instance integer y = 20
int y = 20;
}
// Child class
class Child extends Parent {
// initializing instance integer i = 100
int i = 100;
// first instance block of Child class
{
methodTwo();
System.out.println("Child First Instance Block");
}
// constructor of Child class
Child()
{
System.out.println("Child Class Constructor");
}
// main method of Child class
public static void main(String[] args)
{
// create Child class object
Child c = new Child();
System.out.println("Child Class Main Method");
}
// instance method (methodTwo())
public void methodTwo() { System.out.println(j); }
// second instance block of Child class
{
System.out.println("Child Second Instance Block");
}
// initializing instance integer j = 200
int j = 200;
}
Java
// DirectIndirectRead class
class DirectIndirectRead {
// initializing instance integer i = 10
int i = 10;
// instance block
{
methodOne(); // -> Indirect Read
System.out.println(i); // -> Direct Read
}
// instance method (methodOne())
public void methodOne() { System.out.println(i); }
// main method
public static void main(String[] args)
{
// create DirectIndirectRead class object
DirectIndirectRead d = new DirectIndirectRead();
}
}
Java
// RIWODemo1 class
class RIWODemo1 {
// instance block
{
System.out.println(i); // -> Direct Read
}
// main method
public static void main(String[] args)
{
// create RIWODemo1 class object
RIWODemo1 r = new RIWODemo1();
}
// initializing instance integer i = 10
int i = 10;
}
Java
// RIWODemo2 class
class RIWODemo2 {
// instance block
{
methodOne();
}
// instance method (methodOne())
public void methodOne() { System.out.println(i); }
// main method
public static void main(String[] args)
{
// create RIWODemo2 class object
RIWODemo2 r = new RIWODemo2();
}
// initializing instance integer i = 10
int i = 10;
}
Java
// RW class
class RW {
// initializing instance integer i = 10
int i = 10;
// instance block
{
System.out.println(i);
}
// main method
public static void main(String[] args)
{
// create RW class object
RW r = new RW();
}
}
0
First Instance Block
Second Instance Block
Constructor
Main method
解释:
执行上述程序时,首先会发生静态控制流机制,其中创建类对象,从而使实例控制流机制按以下顺序工作。
首先,它将从上到下识别实例成员。在第一步中识别实例成员后,从上到下执行两个实例块。首先,在第一个实例块中,我们调用methodOne()方法并在该方法中打印变量“j”的值。 JVM 将变量 'j' 的值打印为 0,因为它刚刚被初始化并且尚未分配实际值,然后执行第二个实例块。
然后,最后将执行构造函数。
注意:静态控制流是一次性活动,它将在类加载时执行,但实例控制流不是每次创建对象时都会执行的一次性活动。
父子关系中的实例控制流
每当我们创建子类对象时,以下事件序列将自动执行:
- 识别从父到子的实例成员。
- 仅在父类中执行实例变量赋值和实例块。
- 父类构造函数的执行。
- 在 Child 类中执行实例变量赋值和实例块。
- 子类构造函数的执行。
例子:
Java
// Parent class
class Parent {
// initializing instance integer x = 10
int x = 10;
// first instance block of Parent class
{
// call instance method (methodeOne())
methodOne();
System.out.println("Parent First Instance Block");
}
// constructor of Parent class
Parent()
{
System.out.println("Parent Class Constructor");
}
// main method of Parent class
public static void main(String[] args)
{
// create Parent class object
Parent p = new Parent();
System.out.println("Parent Class Main Method");
}
// instance method (methodOne())
public void methodOne() { System.out.println(y); }
// initializing instance integer y = 20
int y = 20;
}
// Child class
class Child extends Parent {
// initializing instance integer i = 100
int i = 100;
// first instance block of Child class
{
methodTwo();
System.out.println("Child First Instance Block");
}
// constructor of Child class
Child()
{
System.out.println("Child Class Constructor");
}
// main method of Child class
public static void main(String[] args)
{
// create Child class object
Child c = new Child();
System.out.println("Child Class Main Method");
}
// instance method (methodTwo())
public void methodTwo() { System.out.println(j); }
// second instance block of Child class
{
System.out.println("Child Second Instance Block");
}
// initializing instance integer j = 200
int j = 200;
}
0
Parent First Instance Block
Parent Class Constructor
0
Child First Instance Block
Child Second Instance Block
Child Class Constructor
Child Class Main Method
解释:
执行上述程序时,首先会发生静态控制流机制,其中创建子类对象,从而使实例控制流机制按以下顺序工作。
首先,它将识别从父到子的实例成员。第一步识别实例成员后,实例块在Parent类中自上而下执行。首先,在 Parent 类的第一个实例块中,我们调用methodOne()方法并在该方法中打印变量 'y' 的值。 JVM 将变量 'y' 的值打印为 0,因为它刚刚初始化并且尚未分配实际值,然后执行父类构造函数。
其次,实例块在Child类中从上到下执行。在 Child 类的第一个实例块中,我们调用 methodTwo() 方法并在该方法中打印变量“j”的值。 JVM 将变量j的值打印为 0,因为它刚刚被初始化,尚未分配实际值。
然后最后执行 Child 类构造函数。
注意:对象创建是Java中成本最高的操作,因此如果没有特定要求,永远不建议创建对象。
直接和间接参考
在实例块内部,如果我们尝试读取一个变量,则读取操作称为Direct Read 。在实例块内部,如果我们正在调用一个方法,并且在该方法中如果我们尝试读取一个变量,则读取操作称为Indirect Read 。
例子:
Java
// DirectIndirectRead class
class DirectIndirectRead {
// initializing instance integer i = 10
int i = 10;
// instance block
{
methodOne(); // -> Indirect Read
System.out.println(i); // -> Direct Read
}
// instance method (methodOne())
public void methodOne() { System.out.println(i); }
// main method
public static void main(String[] args)
{
// create DirectIndirectRead class object
DirectIndirectRead d = new DirectIndirectRead();
}
}
10
10
1. RIWO (Read Indirectly Write Only) 状态
如果一个变量只是被 JVM 识别并且是原始值,而不是被赋值,那么这个变量被称为处于 RIWO[Read Indirectly Write Only] 状态。如果变量处于RIWO [Read Indirectly Write Only] 状态,那么我们不能执行Direct Read但我们可以执行Indirect Read 。如果我们试图直接读取,那么我们会得到一个编译时错误,说:
示例 1
Java
// RIWODemo1 class
class RIWODemo1 {
// instance block
{
System.out.println(i); // -> Direct Read
}
// main method
public static void main(String[] args)
{
// create RIWODemo1 class object
RIWODemo1 r = new RIWODemo1();
}
// initializing instance integer i = 10
int i = 10;
}
输出
prog.java:6: error: illegal forward reference
System.out.println(i); // -> Direct Read
^
1 error
示例 2
Java
// RIWODemo2 class
class RIWODemo2 {
// instance block
{
methodOne();
}
// instance method (methodOne())
public void methodOne() { System.out.println(i); }
// main method
public static void main(String[] args)
{
// create RIWODemo2 class object
RIWODemo2 r = new RIWODemo2();
}
// initializing instance integer i = 10
int i = 10;
}
0
2. R&W(读写)状态
在 R&W(读和写)状态下,JVM 将它们各自的原始值分配给代码中提到的变量。
例子:
Java
// RW class
class RW {
// initializing instance integer i = 10
int i = 10;
// instance block
{
System.out.println(i);
}
// main method
public static void main(String[] args)
{
// create RW class object
RW r = new RW();
}
}
10