代码块的详解

目录

基本介绍

代码块注意事项

代码块的好处

代码块注意事项和使用细节

代码块习题

第一题

思路分析:

第二题

思路分析:


基本介绍

代码化块又称为初始化块,属于类中的成员[即 是类的一部分],类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。 但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。

基本语法

修饰符;{

}

代码演示:

package idea.chapter10.codeblock_;

/**
 * 演示代码块的基本使用
 */
public class codeBlock01 {
    public static void main(String[] args) {
        /*
        基本介绍
        代码化块又称为初始化块,属于类中的成员[即 是类的一部分],类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。
        但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。
        */

        //怎么理解代码块是什么,我们看到,在Cat类中我们定义了三个构造器,这三个构造器中,都输出了两个相同的话
        //我们在代码块的基本介绍中看到了,代码块是在加载类的时候,或者创建对象的时候隐式调用,
        //定义了代码块之后,不管创建那个对象,都会先调用代码块中的内容

        //因为实在加载类的时候调用的,所以我们只要创建了一个对象,那么就会导致,代买快中的内容被执行
        Cat cat = new Cat();
        
    }
}


//创建了一个Cat类
class Cat {
    //定义了两个私有属性
    private String name;
    private int age;

    //(1) 我们可以看到下面的三个构造器都有相同的语句
    //(2) 这样代码看起来比较冗余
    //(3) 这时我们可以把相同的语句,放入到一个代码块中,即可
    //(4) 这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
    //(5) 代码块调用的顺序优先于构造器..

    {
        System.out.println("猫在叫");
        System.out.println("猫在吃饭");
    }

    //无参构造器
    public Cat() {
//        System.out.println("猫在叫");
//        System.out.println("猫在吃饭");
    }

    //带两个参数的构造器
    public Cat(String name, int age) {
//        System.out.println("猫在叫");
//        System.out.println("猫在吃饭");
        this.name = name;
        this.age = age;
    }

    //带一个参数的构造器
    public Cat(String name) {
//        System.out.println("猫在叫");
//        System.out.println("猫在吃饭");
        this.name = name;
    }
}

代码块注意事项

1)修饰符 可选,要写的话,也只能写static

2)代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块。

3)逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)

4);号可以写上,也可以省略。

代码块的好处

1)相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作

2)场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用

代码块注意事项和使用细节

1)static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行。

2)类什么时候被加载[重要背!]

1.创建对象实例时

2.创建子类对象实例,父类也会被加载

3.使用类的静态成员时(静态属性,静态方法)

3)普通的代码块,在创建对象实例时,会被隐式的调用。 被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。

小结:

1.static代码块是类加载时,执行,只会执行一次

2.普通代码块是在创建对象时调用的,创建一次,调用一次

3.类加载的3种情况,需要记住。

代码演示:

注意

如果是继承的情况下,使用子类的静态属性,也会导致父类被加载

package idea.chapter10.codeblock_;

/**
 * 演示代码块的细节1
 */
public class codeBlockDetail {
    public static void main(String[] args) {
        //1)static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行。

        //2)类什么时候被加载[重要背!]
        //1.创建对象实例时(new)
        //AA aa = new AA();//这句话就会导致AA类的静态代码块被执行

        //2.创建子类对象实例,父类也会被加载
        //AA aa1 = new AA();//因为AA继承了BB所以,会导致BB类的静态代码块也会被执行,并且是先执行父类的静态代码块

        //3.使用类的静态成员时(静态属性,静态方法) 使用子类的静态属性,也导致父类的加载
        //System.out.println(Cat1.n1);//使用了Cat1类的静态属性,也会导致Cat1类中的静态代码块被执行,并且我们继承了Animal类,因此会先执行父类的静态代码块,在到子类的静态代码块

        //static代码块,是在类加载时,执行的,而且只会执行一次.
        //只会执行一次静态代码块中的内容,因为静态代码块是发生在类加载的时候的,类只会加载一次,所以静态代码块只会执行一次
        //普通代码块是,每创建一个对象,就会调用一次
        //DD dd = new DD();
        //DD dd1 = new DD();

        //3)普通的代码块,在创建对象实例时,会被隐式的调用。
        // 被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行。
        System.out.println(DD.n1);//因为我们只是,使用DD类的静态属性,所以会导致类被加载,因此一定会执行静态代码块中的内容,因为我们并没有创建对象,所以普通代码块中的内容不会被执行

        //小结:
        //1.static代码块是类加载时,执行,只会执行一次*
        //2.普通代码块是在创建对象时调用的,创建一次,调用一次
        //3.类加载的3种情况,需要记住。
    }
}

class DD {
    public static int n1 = 8888;//静态属性

    //静态代码块
    static {
        System.out.println("DD 的静态代码块被执行...");//
    }

    //普通代码块, 在new 对象时,被调用,而且是每创建一个对象,就调用一次
    //可以这样简单的,理解 普通代码块是构造器的补充
    {
        System.out.println("DD 的普通代码块...");
    }
}

class Animal {
    //静态代码块
    static {
        System.out.println("Animal 的静态代码块被执行...");//
    }
}

class Cat1 extends Animal {

    public static int n1 = 999;//静态属性

    //静态代码块
    static {
        System.out.println("Cat 的静态代码块被执行...");//
    }
}

class BB {
    //静态代码块
    static {
        System.out.println("BB的静态代码块被执行");
    }
}

class AA extends BB {
    //静态代码块
    static {
        System.out.println("AA的静态代码块被执行");
    }
}

4)创建一个对象时,在一个类 调用顺序是:(重点,难点)

1.调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)[举例说明]

2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)

3.调用构造方法。

思路分析:

1.根据结论我们可以知道,在创建一个对象的时候,会先调用静态代码块和静态属性,但是因为静态代码块和静态属性优先级都一样,所以如果有多个静态代码块和静态属性,那么就按照定义的顺序的调用
  所以因为在A类中,同时有一个静态代码块和静态属性,因为静态代码块定义在上面,所以优先执行静态代码块中的内容,因此会执行静态代码块中的内容(System.out.println("A 静态代码块01");)
  然后去,执行初始化,静态属性,因为n1是通过getN1()方法进行赋值,所以会输出第二句话(System.out.println("getN1被调用...");)
2.在静态属性和静态初始化结束后,就会到我们的普通属性和普通代码块,他们的优先级也是一样的,所以,如果存在,多个普通属性和普通代码块,也是按照定义的顺序去调用,
  所以会执行第三句话也就是普通代码块中的内容(  System.out.println("A 普通代码块01");)  然后去初始化普通属性n2所以,因为n2是通过getN2()去赋值的
  所以会输出第四句话(System.out.println("getN2被调用...");)
3.最后,在静态属性和静态代码块,普通属性和普通代码块结束之后,最后才是我们的构造器,所以第五句话输出的就是(System.out.println("A() 构造器被调用");)

代码演示:

package com.codeblock_;

/**
 * 演示代码块的细节2
 */
public class codeBlockDetail02 {
    public static void main(String[] args) {
        A a = new A();// (1) A 静态代码块01 (2) getN1被调用...(3)A 普通代码块01(4)getN2被调用...(5)A() 构造器被调用

        /*
        思路分析
        1.根据结论我们可以知道,在创建一个对象的时候,会先调用静态代码块和静态属性,但是因为静态代码块和静态属性优先级都一样,所以如果有多个静态代码块和静态属性,那么就按照定义的顺序的调用
          所以因为在A类中,同时有一个静态代码块和静态属性,因为静态代码块定义在上面,所以优先执行静态代码块中的内容,因此会执行静态代码块中的内容(System.out.println("A 静态代码块01");)
          然后去,执行初始化,静态属性,因为n1是通过getN1()方法进行赋值,所以会输出第二句话(System.out.println("getN1被调用...");)
        2.在静态属性和静态初始化结束后,就会到我们的普通属性和普通代码块,他们的优先级也是一样的,所以,如果存在,多个普通属性和普通代码块,也是按照定义的顺序去调用,
          所以会执行第三句话也就是普通代码块中的内容(  System.out.println("A 普通代码块01");)  然后去初始化普通属性n2所以,因为n2是通过getN2()去赋值的
          所以会输出第四句话(System.out.println("getN2被调用...");)
        3.最后,在静态属性和静态代码块,普通属性和普通代码块结束之后,最后才是我们的构造器,所以第五句话输出的就是(System.out.println("A() 构造器被调用");)
         */

        /*
        结论:
        4)创建一个对象时,在一个类 调用顺序是:(重点,难点):
        1.调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)[举例说明]
        2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
        3.调用构造方法。
         */
    }
}

class A {
    { //普通代码块
        System.out.println("A 普通代码块01");//3
    }

    private int n2 = getN2();//普通属性的初始化


    static { //静态代码块
        System.out.println("A 静态代码块01");//1
    }

    //静态属性的初始化
    private static int n1 = getN1();

    public static int getN1() {
        System.out.println("getN1被调用...");//2
        return 100;
    }

    public int getN2() { //普通方法/非静态方法
        System.out.println("getN2被调用...");//4
        return 200;
    }

    //无参构造器
    public A() {
        System.out.println("A() 构造器被调用");//5
    }

}

5)构造方法(构造器)的最前面其实隐含了 super 和 调用普通代码块,新写一个 类演示【截图+说明],静态相关的代码块,属性初始化,在类加载时,就执行完毕 ,因此是优先于 构造器和普通代码块执行的

思路分析:

1.通过结论我们可以知道,在构造器最后,最前面其实隐含了super()和调用普通代码块,所以我们在执行new BBB();这句话之后,就会去执行BBB类的无参构造器
  因为BBB类的无参构造器中,隐含了super()和执行普通代码块,因为BBB继承了AAA所以会去执行AAA类的无参构造器,在AAA类的无参构造器中,也有隐藏的super和执行普通代码块
  因为AAA类的父类是Object所以没有继续执行父类的构造器,因此会先输出AAA类中的普通代码块中的内容(System.out.println("AAA的普通代码块");),
  然后会去执行AAA类的无参构造器中的内容,也就是第二句话(System.out.println("AAA() 构造器被调用....");),
  在执行完父类的普通代码块后,和构造器之后,然后就会回到BBB类的无参构造器,所以会去执行BBB类的普通代码块,因为刚刚发生的内容都是在父类发生的,所以还要继续执行BBB类的普通代码块
  也就是第三句话(System.out.println("BBB的普通代码块...");),最后输出BBB类构造器中的内容,也就是第四句话( System.out.println("BBB() 构造器被调用....");)

代码演示:

package com.codeblock_;

/**
 * 演示代码块的细节3
 */

public class codeBlockDetail03 {
    public static void main(String[] args) {
        new BBB();//(1)AAA的普通代码块(2)AAA() 构造器被调用(3)BBB的普通代码块(4)BBB() 构造器被调用

        /*
        思路分析:
        1.通过结论我们可以知道,在构造器最后,最前面其实隐含了super()和调用普通代码块,所以我们在执行new BBB();这句话之后,就会去执行BBB类的无参构造器
          因为BBB类的无参构造器中,隐含了super()和执行普通代码块,因为BBB继承了AAA所以会去执行AAA类的无参构造器,在AAA类的无参构造器中,也有隐藏的super和执行普通代码块
          因为AAA类的父类是Object所以没有继续执行父类的构造器,因此会先输出AAA类中的普通代码块中的内容(System.out.println("AAA的普通代码块");),
          然后会去执行AAA类的无参构造器中的内容,也就是第二句话(System.out.println("AAA() 构造器被调用....");),
          在执行完父类的普通代码块后,和构造器之后,然后就会回到BBB类的无参构造器,所以会去执行BBB类的普通代码块,因为刚刚发生的内容都是在父类发生的,所以还要继续执行BBB类的普通代码块
          也就是第三句话(System.out.println("BBB的普通代码块...");),最后输出BBB类构造器中的内容,也就是第四句话( System.out.println("BBB() 构造器被调用....");)
         */

        //结论
        //5)构造方法(构造器)的最前面其实隐含了 super 和 调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕 ,因此是优先于 构造器和普通代码块执行的
    }
}

class AAA { //父类Object
    {
        System.out.println("AAA的普通代码块");//1
    }

    public AAA() {
        //(1)super()
        //(2)调用本类的普通代码块
        System.out.println("AAA() 构造器被调用....");//2
    }
}

class BBB extends AAA {
    {
        System.out.println("BBB的普通代码块...");//3
    }

    public BBB() {
        //(1)super()
        //(2)调用本类的普通代码块
        System.out.println("BBB() 构造器被调用....");//4
    }
}

6)我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下

①父类的静态代码块和静态属性(优先级一样,按定义顺序执行)

②子类的静态代码块和静态属性(优先级一样,按定义顺序执行)

父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)

④父类的构造方法

⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)

⑥子类的构造方法//面试题

7)静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调 用任意成员。

思路分析:

1.通过结论我们可以知道,在一个子类在继承了父类之后,再去创建子类对象的时候,会先去支持父类的静态代码块和静态属性,如果有多个静态代码块和静态属性,那么按照定义的顺序执行
  所以会先去执行父类的静态属性,因为在父类的第一行,因为父类的n1属性是同过getVal01()方法赋值,所以会输出第一句话(System.out.println("getVal01");) ,
  然后再去执行父类的静态代码块,所以就会输出第二句话(System.out.println("A02的一个静态代码块..");)

2.然后再去执行子类的静态属性和静态代码块,因为子类的静态属性n3定义在第一行,所以会先执行n3属性,因为n3属性是通过getVal03()进行赋值,所以会输出第三局话(System.out.println("getVal03");)
  然后再去执行子类的静态代码块,因此会输出第四句话(System.out.println("B02的一个静态代码块..");)

3.然后会去执行父类的普通代码块和普通属性的初始化,如果有多个普通属性和普通代码块他们的优先级一样,按照顺序去执行
  所以会去父类的普通代码块就会输出第五句话(System.out.println("A02的第一个普通代码块..");)
  然后再去初始化父类的普通属性,因为父类的普通属性是通过getVal02()赋值的,所以会输出第六句话( System.out.println("getVal02");)

4.然后就是执行父类的构造器,也就是会输出第7句话(System.out.println("A02的构造器");)

5.然后会去执行字类的普通代码块和普通属性的初始化,如果有多个普通属性和普通代码块他们的优先级一样,按照顺序去执行
  所以会先去初始化子类的普通普通属性,因为子类的普通属性是通过getVal04()赋值的,所以会输出第八句话(System.out.println("getVal04");)
  然后再去执行子类的普通代码块,就会输出第9句话也就是(System.out.println("B02的第一个普通代码块..");)

6.最后会去执行子类的无参构造器,就会输出第10句话(System.out.println("B02的构造器");)

代码演示:

package com.codeblock_;

/**
 * 演示代码块的细节4
 */
public class codeBlockDetail04 {
    public static void main(String[] args) {

        //(1) 进行类的加载
        //1.1 先加载 父类 A02 1.2 再加载 B02
        //(2) 创建对象
        //2.1 从子类的构造器开始
        new B02();//对象
        /*
        思路分析:
        1.通过结论我们可以知道,在一个子类在继承了父类之后,再去创建子类对象的时候,会先去支持父类的静态代码块和静态属性,如果有多个静态代码块和静态属性,那么按照定义的顺序执行
          所以会先去执行父类的静态属性,因为在父类的第一行,因为父类的n1属性是同过getVal01()方法赋值,所以会输出第一句话(System.out.println("getVal01");) ,
          然后再去执行父类的静态代码块,所以就会输出第二句话(System.out.println("A02的一个静态代码块..");)

        2.然后再去执行子类的静态属性和静态代码块,因为子类的静态属性n3定义在第一行,所以会先执行n3属性,因为n3属性是通过getVal03()进行赋值,所以会输出第三局话(System.out.println("getVal03");)
          然后再去执行子类的静态代码块,因此会输出第四句话(System.out.println("B02的一个静态代码块..");)

        3.然后会去执行父类的普通代码块和普通属性的初始化,如果有多个普通属性和普通代码块他们的优先级一样,按照顺序去执行
          所以会去父类的普通代码块就会输出第五句话(System.out.println("A02的第一个普通代码块..");)
          然后再去初始化父类的普通属性,因为父类的普通属性是通过getVal02()赋值的,所以会输出第六句话( System.out.println("getVal02");)

        4.然后就是执行父类的构造器,也就是会输出第7句话(System.out.println("A02的构造器");)

        5.然后会去执行字类的普通代码块和普通属性的初始化,如果有多个普通属性和普通代码块他们的优先级一样,按照顺序去执行
          所以会先去初始化子类的普通普通属性,因为子类的普通属性是通过getVal04()赋值的,所以会输出第八句话(System.out.println("getVal04");)
          然后再去执行子类的普通代码块,就会输出第9句话也就是(System.out.println("B02的第一个普通代码块..");)

        6.最后会去执行子类的无参构造器,就会输出第10句话(System.out.println("B02的构造器");)
         */


        /*
        结论
        (6)我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下
        1.父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
        2.子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
        3.父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
        4.父类的构造方法
        5.子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
        6.子类的构造方法

        (7)静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调 用任意成员。
         */
    }
}

class A02 { //父类
    private static int n1 = getVal01();

    static {
        System.out.println("A02的一个静态代码块..");//(2)
    }

    {
        System.out.println("A02的第一个普通代码块..");//(5)
    }

    public int n3 = getVal02();//普通属性的初始化

    public static int getVal01() {
        System.out.println("getVal01");//(1)
        return 10;
    }

    public int getVal02() {
        System.out.println("getVal02");//(6)
        return 10;
    }

    public A02() {//构造器
        //隐藏
        //super()
        //普通代码和普通属性的初始化......
        System.out.println("A02的构造器");//(7)
    }

}

class B02 extends A02 { //

    private static int n3 = getVal03();

    static {
        System.out.println("B02的一个静态代码块..");//(4)
    }

    public int n5 = getVal04();

    {
        System.out.println("B02的第一个普通代码块..");//(9)
    }

    public static int getVal03() {
        System.out.println("getVal03");//(3)
        return 10;
    }

    public int getVal04() {
        System.out.println("getVal04");//(8)
        return 10;
    }

    //一定要慢慢的去品..
    public B02() {//构造器
        //隐藏了
        //super()
        //普通代码块和普通属性的初始化...
        System.out.println("B02的构造器");//(10)
        // TODO Auto-generated constructor stub
    }
}

// (7)静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调 用任意成员。
class C02 {
    private int n1 = 100;
    private static int n2 = 200;

    private void m1() {

    }

    private static void m2() {

    }

    static {
        //静态代码块,只能调用静态成员
        //System.out.println(n1);错误
        System.out.println(n2);//ok
        //m1();//错误
        m2();
    }

    {
        //普通代码块,可以使用任意成员
        System.out.println(n1);
        System.out.println(n2);//ok
        m1();
        m2();
    }
}

代码块习题

第一题

思路分析:

1.因为使用类的静态属性会导致类的加载,所以在我们第一次使用Person.total的时候,就会先去执行静态代码块,在静态代码块中给total赋值了100
  然后在输出(System.out.println("in static block!");)这句话,然后就是输出total的值,第二次在一次输出total的时候,不会再输出其他内容
  只会输出total的值,因为类的加载只会发生一次
  因此最后输出的内容就是
  in static block!
  total = 100
  total = 100

重点
2)类什么时候被加载
1.创建对象实例时
2.创建子类对象实例,父类也会被加载
3.使用类的静态成员时(静态属性,静态方法)
package com.codeblock_;

public class codeBlockExercise01 {
    public static void main(String[] args) {
        System.out.println("total = " + Person.total); //100
        System.out.println("total = " + Person.total); //100
        /*
        思路分析:
        1.因为使用类的静态属性会导致类的加载,所以在我们第一次使用Person.total的时候,就会先去执行静态代码块,在静态代码块中给total赋值了100
          然后在输出(System.out.println("in static block!");)这句话,然后就是输出total的值,第二次在一次输出total的时候,不会再输出其他内容
          只会输出total的值,因为类的加载只会发生一次
          因此最后输出的内容就是
          in static block!
          total = 100
          total = 100
            
        重点  
        2)类什么时候被加载 
        1.创建对象实例时
        2.创建子类对象实例,父类也会被加载 
        3.使用类的静态成员时(静态属性,静态方法)
         */
    }
}

class Person {
    public static int total;//静态变量

    static {//静态代码块
        total = 100;
        System.out.println("in static block!");//(1)
    }
}

第二题

思路分析:

1.我们创建了一个Test对象,就会导致类的加载,所以会先执行静态属性和静态代码块,因为Test类中有多个静态属性和静态代码块,因此按照顺序执行
  所以会先执行    static Sample sam = new Sample("静态成员sam初始化 "); 这句话 ,这句话执行了后,就会去执行Sample类的有参构造器
  会输出第一句话(System.out.println(静态成员sam初始化);)

2.然后会去执行静态代码块中的内容,会输出第二句话(System.out.println("static块执行");) 因为我们在执行静态代码块的时候,已经创建了Sample对象
  所以此时再去判断 sam==null 不成立,所以就不会输出if语句中的内容

3.然后再去执行普通属性和普通代码块的初始化,所以会执行      Sample sam1 = new Sample("sam1成员初始化"); 这句话,会导致去调用父类的有参构造器
  所以会输出第三局话(System.out.println(sam1成员初始化);)

4.最后一步,执行子类的构造器,输出第四句话(System.out.println("Test默认构造函数被调用");)
package com.codeblock_;

public class codeBlockExercise02 {
    public static void main(String str[]) {
        Test a = new Test();//无参构造器
        //会先执行静态代码块和静态属性 然后在去执行非静态代码块和属性
        //再去先去调用Test()类的无参构造器 无参构造器中会有一个隐藏的super()

        /*
        思路分析:
        1.我们创建了一个Test对象,就会导致类的加载,所以会先执行静态属性和静态代码块,因为Test类中有多个静态属性和静态代码块,因此按照顺序执行
          所以会先执行    static Sample sam = new Sample("静态成员sam初始化 "); 这句话 ,这句话执行了后,就会去执行Sample类的有参构造器
          会输出第一句话(System.out.println(静态成员sam初始化);) 
          
        2.然后会去执行静态代码块中的内容,会输出第二句话(System.out.println("static块执行");) 因为我们在执行静态代码块的时候,已经创建了Sample对象
          所以此时再去判断 sam==null 不成立,所以就不会输出if语句中的内容
          
        3.然后再去执行普通属性和普通代码块的初始化,所以会执行      Sample sam1 = new Sample("sam1成员初始化"); 这句话,会导致去调用父类的有参构造器
          所以会输出第三局话(System.out.println(sam1成员初始化);)
          
        4.最后一步,执行子类的构造器,输出第四句话(System.out.println("Test默认构造函数被调用");)  
         */
    }
}


class Sample {
    Sample(String s) {
        System.out.println(s);
    }

    Sample() {
        System.out.println("Sample默认构造函数被调用");//
    }
}

class Test {
    Sample sam1 = new Sample("sam1成员初始化");//3
    static Sample sam = new Sample("静态成员sam初始化 ");//1

    static {
        System.out.println("static块执行");//2
        if (sam == null) System.out.println("sam is null");
    }

    Test() {//构造器
        System.out.println("Test默认构造函数被调用");//4
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值