java中的代码块

基本介绍:

概念:

代码块又称为初始化块,属于类中的成员[即是类的一部分],类似于方法(可以看作只有方法体的方法),讲逻辑语句封装在方法体 中,通过{ }包围起来。

但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过对象或者类显式调用,而是加载类时,或创建对象时隐式调用。

基本语法:

[修饰符]{
    代码
};

细节:

1)修饰符可写可不写,如果写必须是static;

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

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

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

代码块的好处:

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

2)如果多个构造器存在重复语句,可以抽取到初始化块中,提高代码的重用性;

3)举例说明:

public class Test{
 
    public static void main(String[] args){
        Student tom = new Student("tom");
        Student jack = new Student("jack",18);
        Student smith = new Student("smith,22,10001);
    }
}
class Student{
    //私有属性
    private String name;
    private int age;
    private long id;
    //代码块
    {
        System.out.println("即将对学生点名!");
        System.out.println("即将核对学生年龄!");
        System.out.println("即将核对学生学号!");
    }
    //构造器    
    public Student(String name){
        this.name = name;
        System.out.println("调用了Student类的Student(String name)构造器");
    }
    public Student(String name , int age){
        this.name = name;
        this.age = age;
        System.out.println("调用了Student类的Student(String name , int age)构造器");
    }
    public Student(String name , int age , long id){
        this.name = name;
        this.age = age;
        this.id = id;
        System.out.println("调用了Student类的Student(String name , int age , long id)构造器");
    }
}

输出结果:

即将对学生点名!

即将核对学生年龄!

即将核对学生学号!

调用了Student类的Student(String name)构造器

即将对学生点名!

即将核对学生年龄!

即将核对学生学号!

调用了Student类的Student(String name , int age)构造器

即将对学生点名!

即将核对学生年龄!

即将核对学生学号!

调用了Student类的Student(String name , int age , long id)构造器
 

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


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

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

①创建对象实例时(Student student = new Student(););
②创建子类对象实例,父类也会被加载;
③使用类的静态成员时(静态属性、静态方法)
package com.pero.codeblock;
 
/**
 * 类加载的三种情况
 * @version 1.0
 * @author Pero
 */
 
public class Test01 {
    public static void main(String[] args) {
        //类被加载的情况举例
        //1.创建对象实例时
        //Person person = new Person();
        //2.创建子类对象实例,父类也会被加载,父类先被加载,子类后被加载
        //Student student = new Student();
        //3.使用类的静态成员时(静态属性、静态方法)
        System.out.println(Teacher.age);
    }
}
class Person {
    //静态代码块
    static {
        System.out.println("Person类的静态代码块1被执行");
    };
}
 
class Student extends Person{
    //静态代码块
    static {
        System.out.println("Student类的静态代码块1被执行");
    };
}
 
class Teacher{
    public static int age = 26;
 
    //静态代码块
    static {
        System.out.println("Teacher类的静态代码块1被执行");
    }
}
3)普通代码块,在创建对象实例时,会被隐式调用。被创建一次,就会调用一次。(可以将普通代码块看作构造器的补充,构造器被调用,他就会被调用)
package com.pero.codeblock;
 
/**
 * 类加载的三种情况
 * @version 1.0
 * @author Pero
 */
 
public class Test01 {
    public static void main(String[] args) {
        //类被加载的情况举例
        //1.创建对象实例时
        //Person person = new Person();
        //2.创建子类对象实例,父类也会被加载,父类先被加载,子类后被加载
        //Student student = new Student();
        //3.使用类的静态成员时(静态属性、静态方法)
        //System.out.println(Teacher.age);
 
        //类加载时,静态代码块只执行一次
        //普通代码块在创建对象实例时,会被隐式调用,创建一次就调用一次
        //如果只是使用类的静态成员时,普通代码块不会被执行
        Teacher teacher1 = new Teacher();
        Teacher teacher2 = new Teacher();
        System.out.println(Teacher.age);
 
    }
}
class Person {
    //静态代码块
    static {
        System.out.println("Person类的静态代码块1被执行");
    };
}
 
class Student extends Person{
    //静态代码块
    static {
        System.out.println("Student类的静态代码块1被执行");
    };
}
 
class Teacher{
    public static int age = 26;
 
    //静态代码块
    static {
        System.out.println("Teacher类的静态代码块1被执行");
    }
    //普通代码块
    {
        System.out.println("Teacher类的普通代码块1被执行");
    };
}
4)创建一个对象时,在一个类调用顺序是:

①调用静态代码块和静态属性初始化(注意:    静态代码块和静态属性  初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,按照定义顺序(谁写前面先调用谁)调用);
②调用普通代码块和普通属性的初始化(注意:普通话代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,按照定义顺序调用);
③调用构造方法;
 
package com.pero.codeblock;
 
/**
 * 创建一个对象时,在一个类调用顺序是:
 * ①调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,
 * 如果有多个静态代码块和多个静态变量初始化,按照定义顺序调用);
 * ②调用普通代码块和普通属性的初始化(注意:普通话代码块和普通属性初始化调用的优先级一样,
 * 如果有多个普通代码块和多个普通属性初始化,按照定义顺序调用);
 * ③调用构造方法;
 *
 * @version 1.1
 * @author Pero
 */
 
public class Test02 {
    public static void main(String[] args) {
        Model01 model01 = new Model01();
        //(1)Model01静态属性被执行,getNumber1被调用
        // (2)Model01的静态代码块1被执行
        // (3)Model01普通属性被执行,getNumber2被调用
        // (4)Model01的普通代码块1被执行
        // (5)Model01构造器被执行
    }
}
class Model01{
 
    //普通属性的初始化
    private int number2 = getNumber2();
 
    //静态属性的初始化
    private static int number1 = getNumber1();
 
    //无参构造器
    public Model01(){
        System.out.println("Model01的构造器被执行");
    }
 
    //普通代码块
    {
        System.out.println("Model01的普通代码块1被执行");
    };
 
    //静态代码块
    static {
        System.out.println("Model01的静态代码块1被执行");
    };
 
    //静态方法
    public static int getNumber1(){
        System.out.println("静态方法getNumber1()方法被调用");
        return 100;
    }
    //普通方法
    public int getNumber2(){
        System.out.println("普通方法getNumber2()方法被调用");
        return 200;
    }
 
 
}
5)构造器的前面隐含了super()和普通代码块的执行,静态相关的代码块和属性的初始化在类加载时就已经执行完毕,因此是优先于普通代码块和属性的初始化及构造器的执行; 
package com.pero.codeblock;
 
/**
 * 构造器的前面隐含了super()和普通代码块的执行,
 * 静态相关的代码块和属性的初始化在类加载时就已经执行完毕,
 * 因此是优先于普通代码块和属性的初始化及构造器的执行;
 *
 * @version 1.3
 * @author Pero
 */
public class Test03 {
    public static void main(String[] args) {
        new T02();
        // (1)T01的普通代码块被执行
        // (2)T01构造器被调用
        // (3)T02的普通代码块被调用
        //(4)T02的构造器被调用
    }
}
class T01{
    //父类是Object类
    {
        System.out.println("T01的普通代码块被执行");
    };
    public T01(){
        System.out.println("T01的无参构造器被调用");
    }
}
class T02 extends T01{
    //普通代码块
    {
        System.out.println("T02的普通代码块被执行");
    };
    public T02(){
        //super();
        //调用本类的普通代码块
        System.out.println("T01的无参构造器被调用");
    }
}

先加载后构造,加载静态,构造普通

父静态(按顺序) -> 子静态(按顺序) -> 父普通(按顺序) -> 父构造 -> 子普通(按顺序) -> 子构造
 

6)创建一个子类时(继承关系),父类与子类的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序;

①父类的静态代码块和静态属性(优先级一样,按定义顺序执行);
②子类的静态代码块和静态属性(优先级一样,按定义顺序执行);
③父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行);
④父类构造方法;
⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行);
⑥子类的构造方法;
 
package com.pero.codeblock;
 
/**
 * 创建一个子类时(继承关系),父类与子类的静态代码块,静态属性初始化,普通代码块,
 * 普通属性初始化,构造方法的调用顺序;
 * ①父类的静态代码块和静态属性(优先级一样,按定义顺序执行);
 * ②子类的静态代码块和静态属性(优先级一样,按定义顺序执行);
 * ③父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行);
 * ④父类构造方法;
 * ⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行);
 * ⑥子类的构造方法;
 */
 
public class Test04 {
    public static void main(String[] args) {
        //(1)进行类的加载
        // 1.1先加载父类Animal类(执行静态代码块和属性);
        // 1.2再加载子类Dog类(执行静态代码块和属性);
        //(2)创建对象
        // 从子类的构造器开始
        // 2.1.1 super()
        // 2.1.2 父类的普通代码块和普通属性
        // 2.1.3 父类的构造方法
        // 2.2.1 子类的普通代码块和普通属性
        // 2.2.2 子类的构造方法
        new Dog();
    }
}
class Animal{
 
    private static int a1 = getA1();//(1)
 
    static {
        System.out.println("Animal类的静态代码块1");//(2)
    };
 
    {
        System.out.println("Animal类的普通代码块1");//(5)
    };
 
    public int a2 = getA2();//(6)
 
    public static int getA1(){
        System.out.println("Animal类的getA1静态方法");//(1)
        return 100;
    }
 
    public int getA2(){
        System.out.println("Animal类的getA2普通方法");//(6)
        return 200;
    }
 
    public Animal(){
        //super();
        //普通代码块和属性的初始化
        System.out.println("Animal类的无参构造器");//(7)
    }
}
class Dog extends Animal{
 
    private static int a3 = getA3();//(3)
 
    static {
        System.out.println("Dog类的静态代码块1");//(4)
    };
 
    public int a4 = getA4();//(8)
 
    {
        System.out.println("Dog类的普通代码块1");//(9)
    }
 
    public static int getA3(){
        System.out.println("Dog类的getA3静态方法");//(3)
        return 300;
    }
 
    public int getA4(){
        System.out.println("Dog类的getA4普通方法");//(8)
        return 400;
    }
 
    public Dog(){
        //super();
        //普通代码块和属性的初始化
        System.out.println("Dog类的无参构造器");//(10)
    }
}
7)静态代码块只能调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。
 
class Cat{
    private int n1 = 100;
    private static int n2 = 200;
 
    private void m1(){
        System.out.println("Cat类的普通方法m1()");
    }
    private static void m2(){
        System.out.println("Cat类的静态方法m2()");
    }
 
    //静态代码块
    static {
        //System.out.println(n1);错误
        System.out.println(n2);
        //m1();错误
        m2();
    };
    
    //普通代码块
    {
        System.out.println(n1);
        System.out.println(n2);
        m1();
        m2();
    };
}

练习

第一次Person.total加载类信息  执行上面的 静态属性和静态代码块  输出 in static block  然后输出100

 第一次Person.total,无需加载类信息,直接输出100

输出1)静态成员sam初始化  2)static块被执行 3)sam1成员初始化  4)Test默认构造器函数被调用  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值