📜  Java中的实例控制流

📅  最后修改于: 2022-05-13 01:55:42.270000             🧑  作者: Mango

Java中的实例控制流

本文将解释每当创建对象时实例控制流是如何发生的。

普通类中的实例控制流程

每当我们执行Java .class 文件时,都会执行第一个静态控制流。在静态控制流中,如果我们正在创建一个对象,以下步骤序列将作为实例控制流的一部分执行:

  1. 从上到下标识实例成员。
  2. 从上到下执行实例变量赋值和实例块。
  3. 构造函数的执行。

例子:

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,因为它刚刚被初始化并且尚未分配实际值,然后执行第二个实例块。

然后,最后将执行构造函数。

注意:静态控制流是一次性活动,它将在类加载时执行,但实例控制流不是每次创建对象时都会执行的一次性活动。

父子关系中的实例控制流

每当我们创建子类对象时,以下事件序列将自动执行:

  1. 识别从父到子的实例成员。
  2. 仅在父类中执行实例变量赋值和实例块。
  3. 父类构造函数的执行。
  4. 在 Child 类中执行实例变量赋值和实例块。
  5. 子类构造函数的执行。

例子:

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