Java 面向对象—非静态代码块

一、非静态代码块

  1、声明格式

【修饰符】 class 类名 {
      {
             非静态代码块
       } 
 }    

  2、非静态代码块中的代码执行时机

    (1)在"每次"创建对象的时候执行

    (2)比构造方法早

    Demo:

 1 class MyClass{
 2     private String str;
 3     
 4     public MyClass(){
 5         System.out.println("无参构造2");
 6     }
 7     public MyClass(String str){
 8         this.str = str;
 9         System.out.println("有参构造3");
10     }
11     
12     {
13         System.out.println("非静态代码块1");
14     }
15 }

    运行结果:先执行非静态代码中输出"非静态代码块1",然后执行无参构造方法输出"无参构造2"。

  3、实例初始化过程

    初始化过程:创建对象时,为对象进行初始化的操作

    执行顺序:

① 为成员变量显示赋值

② 执行非静态代码块

③ 执行构造器

    图解:

     

    Java 编译器其实,会把这三个部分的代码,合成一个叫做 <init>(【形参列表】) 实例初始化方法。

    即编译后的 .class 字节码文件中,是没有构造方法这个概念的。

    <init>(【形参列表】) 实例初始化方法的代码就是由三个部分组成:

① 成员变量显示赋值的代码

② 非静态代码中的代码

③ 构造器中的代码

    注意:

      1、其中的 ① 和 ② 按顺序执行,而 ③ 一定是它们当中的最后执行的。

      2、有几个构造器,就会有几个实例初始化方法。那么当创建对象的时候,调用对应的构造器时,其实执行的是对应的实例初始化方法 <init>(【...】)

二、继承中的非静态代码块

  1、继承案例

    先来看一个没有非静态的代码块的继承关系:

    Demo:

 1 public class TestInit {
 2     public static void main(String[] args) {
 3          Father f = new Father();
 4          //执行父类的无参构造
 5 
 6          Son s = new Son();
 7          //先执行父类的无参构造,再执行子类的无参构造
 8 
 9         
10          Son s2 = new Son("HelloWorld");
11          //先执行父类的无参构造,再执行子类的有参构造1
12 
13 
14          Son s3 = new Son("Java", 10);
15          // 先执行父类的无参构造,再执行子类的有参构造1,然后再执行子类的有参构造2
16 
17     }
18 }
19 //父类
20 class Father{
21     public Father(){
22         System.out.println("父类的无参构造");
23     }
24 }
25 // 子类
26 class Son extends Father{
27     private String str;
28     private int num;
29     
30     public Son(){
31         //隐含了super();  子类的构造器中一定会调用父类的构造器,默认调用父类的无参构造
32         System.out.println("子类的无参构造");
33     }
34     
35     public Son(String str){
36         //隐含了super()
37         this.str = str;
38         System.out.println("子类的有参构造1");
39     }
40     
41     public Son(String str,int num){
42         this(str);           //这里有this就不会有super了,然后调用本类中的构造方法
43         this.num = num;
44         System.out.println("子类的有参构造2");
45     }
46 }                

  2、含有非静态代码块的继承关系

    (1)先执行父类的实例初始化方法

      它由三部分组成:

① 成员变量的显示赋值

② 非静态代码块

③ 构造方法

    (2)再执行子类的实例初始化方法

      它由三部分组成:

① 成员变量的显示赋值

② 非静态代码块

③ 构造方法

    注意:

    ① super() 或 super(实参列表) 之前说的是调用父类的构造器,其实是调用父类对应的实例初始化方法

    ② super() 或 super(实参列表) 之前说的是在子类构造器的首行,其实是在子类实例初始化方法的首行,所以会先完成父类的初始化,再进行子类的初始化。

    Demo:

 1 public class TestInit {
 2     public static void main(String[] args) {
 3         Fu f = new Fu();   //312
 4         System.out.println("==========");
 5         Zi z = new Zi();    //312645
 6     }
 7 }
 8 
 9 
10 class Fu{
11     private String strFu = assignFu();
12     {
13         System.out.println("(1)父类的非静态代码块");
14     }
15     public Fu(){
16         System.out.println("(2)父类的无参构造");
17     }
18     public String assignFu(){
19         System.out.println("(3)父类的assignFu()");
20         return "fu";
21     }
22 }
23 class Zi extends Fu{
24     private String strZi = assignZi();
25     {
26         System.out.println("(4)子类的非静态代码块");
27     }
28     public Zi(){
29         //super()  ==>调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
30         System.out.println("(5)子类的无参构造");
31     }
32     
33     public  String assignZi(){
34         System.out.println("(6)子类的assignZi()");
35         return "zi";
36     }
37 }

   运行结果:

     

      图解:

  

  3、含有非静态代码块的重写继承关系

    Demo:

 1 public class TestInit {
 2     public static void main(String[] args) {
 3         Ba b = new Ba();    // 312
 4         System.out.println("============");
 5         Er r = new Er();      //612645,因为子类重写了assign()
 6         
 7     }
 8 }
 9 class Ba{
10     private String str = assign();
11     {
12         System.out.println("(1)父类的非静态代码块");
13     }
14     public Ba(){
15         System.out.println("(2)父类的无参构造");
16     }
17     public String assign(){
18         System.out.println("(3)父类的assign()");
19         return "ba";
20     }
21 }
22 class Er extends Ba{
23     private String str = assign();
24     {
25         System.out.println("(4)子类的非静态代码块");
26     }
27     public Er(){
28         //super()  ==>调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
29         System.out.println("(5)子类的无参构造");
30     }
31     
32     public String assign(){
33         System.out.println("(6)子类的assign()");
34         return "er";
35     }
36 }

  运行结果:

  

  图解:

   注意:this在构造器中,在实例化初始化方法中,代表的是正在创建的对象,当创建子类对象时,因为子类重写的 assign(),那么执行是子类重写的 assign() 方法。

   

原文地址:https://www.cnblogs.com/niujifei/p/11885737.html