• 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() 方法。

       

  • 相关阅读:
    「SDOI2018」物理实验
    「SDOI 2018」战略游戏
    「CodeChef Dec13 REALSET」 Petya and Sequence 循环卷积
    关于微信卡券投放code接口报错原因
    composer update maatwebsite/excel 之后 在linux机子上出现500解决方案
    开启mysql 服务【window】
    thinkphp在linux上部署环境(500情况)
    如何推广微信小程序到企业微信
    linux 阿里云远程连接mysql
    php7以上 不支持mcrypt_module_open方法问题【微信开放平台】
  • 原文地址:https://www.cnblogs.com/niujifei/p/11885737.html
Copyright © 2020-2023  润新知