JAVA代码块

代码块

基本介绍:代码化块又称为初始化块,属性类中的成员【即是类的一部分】,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来

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

基本语法

[修饰符] {代码};

说明注意:

  1. 修饰符可选,要写的话,也只能写static
  2. 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块或非静态代码块
  3. 逻辑语句可以为任何逻辑语句(输入,输出,方法调用,循环,判断等)
  4. ;号可以写上,也可以省略

代码块作用的结论:(记住)

  1. 可以把相同的语句,放入到一个代码块中
  2. 当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
  3. 代码块调用的顺序优先于构造器

代码块的好处和案例演示:

  1. 相当于另外一个形式的构造器(对构造器的补充机制),可以做初始化的操作
  2. 场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性。
  3. 代码块的快速入门:CodeBlock01.java
package JAVA面向对象高级部分.static_.codeBlock;

public class CodeBlock01 {
    public static void main(String[] args) {
        Movie movie = new Movie("寒战2");
        System.out.println("--------------------");
        Movie movie1 = new Movie("无双", 125.168, "无双导演");
    }
}

class Movie{
    private String name;
    private double price;//时长
    private String director;

    /**
     * 代码块的作用:
     * 代码块是优先于构造器执行的
     * 不管用那个构造器初始化,都会调用非静态代码块
     */
    {
        System.out.println("电影屏幕打开。。。");
        System.out.println("电影广告。。。");
        System.out.println("电影开始播放。。。");
    }
    public Movie() {
//        System.out.println("电影屏幕打开。。。");
//        System.out.println("电影广告。。。");
//        System.out.println("电影开始播放。。。");
    }

    public Movie(String name) {
        this.name = name;
        System.out.println("Movie(String name) 构造器被调用。。。");
//        System.out.println("电影屏幕打开。。。");
//        System.out.println("电影广告。。。");
//        System.out.println("电影开始播放。。。");
    }

    public Movie(String name, double price, String director) {
        this.name = name;
        this.price = price;
        this.director = director;
        System.out.println("Movie(String name, double price, String director) 被调用。。。");
//        System.out.println("电影屏幕打开。。。");
//        System.out.println("电影广告。。。");
//        System.out.println("电影开始播放。。。");
    }
}

返回值:
    电影屏幕打开。。。
    电影广告。。。
    电影开始播放。。。
    Movie(String name) 构造器被调用。。。
    --------------------
    电影屏幕打开。。。
    电影广告。。。
    电影开始播放。。。
    Movie(String name, double price, String director) 被调用。。。

代码块的使用注意事项和细节说明(七点必须记住)

静态代码块是针对类的加载的,而普通代码块是针对创建对象初始化的(普通代码块是构造器的补充机制,可以认为是一个特殊的构造器)

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

2.类什么时候被加载(三种情况)【记住】

  1. 创建对象实例时(new)
  2. 创建子类对象实例,父类也会被加载
  3. 使用类的静态成员(成员方法和成员属性)

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

小结:(1)static代码块是类加载时,执行,只会执行一次

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

(3)类加载3种情况,需要记住

注意:当两个类继承关系时,先执行父类的静态代码块,再执行子类的静态代码块,最后再执行父类的非静态代码块和子类的非静态代码块,非静态代码块是创建对象时才会被执行

package JAVA面向对象高级部分.static_.codeBlock;

public class CodeBlockDetail01 {
    public static void main(String[] args) {
//        A a = new A();
//        A a1 = new A();
        /**
         * 返回值是:
             我是静态代码块
             我是普通代码块
             我是普通代码块
         */

        System.out.println("-----------------");
       // C c = new C();
        /**返回值:
         * 我是B类的静态代码块
         * 我是C类的静态代码块
         * 我是B类的非静态代码块
         * 我是C类的非静态代码块
         */

        System.out.println("------------------");
        //注意是:非静态代码块是创建对象时,才会被执行
        //System.out.println(C.name);
        /**
         * 我是B类的静态代码块
         * 我是C类的静态代码块
         * 我是程序员!!!呵呵
         */

        System.out.println("----------------");
        System.out.println(D.number);
        /**
         * 返回值:
         * 我是D类的静态代码块
         * 168
         */
    }
}

/**
 * 第一个细节:
 * static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类加载而执行
 * 并且只会执行一次,如果是普通代码块,每创建一个对象就执行一次
 */
class A {
    //静态代码块,注意代码块只能用static修饰,只会加载一次,随着类加载而加载
    static {
        System.out.println("我是静态代码块");
    }
    //非静态代码块(普通代码块),每创建一个对象就执行一次
    {
        System.out.println("我是普通代码块");
    }
}

/**
 * 类什么时候被加载【必须记住】
 * 1.创建对象实例时(new)
 * 2.创建子类对象实例,父类也会被加载
 * 3.使用类的静态成员时(静态属性或静态方法)
 */

class B {
    //静态代码块
    static {
        System.out.println("我是B类的静态代码块");
    }
    //非静态代码块(普通代码块)
    {
        System.out.println("我是B类的非静态代码块");
    }
}

class C extends B {
    public static String name = "我是程序员!!!呵呵";

    //C类静态代码块
    static {
        System.out.println("我是C类的静态代码块");
    }

    //C类非静态代码块
    {
        System.out.println("我是C类的非静态代码块");
    }
}

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

class D {
    public static int number = 168;

    //静态代码块,在加载类信息时,就会被调用一次,并且只会调用一次
    static {
        System.out.println("我是D类的静态代码块");
    }

    //非静态代码块,如果不创建对象时,是不会调用非静态代码块的,并且创建一次调用一次
    {
        System.out.println("我是D类的非静态代码块");
    }
}

说明使用类的静态成员【成员方法和属性】时,都会使类的加载

代码块细节说明2(记住)

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

  1. 调用静态代码块和静态属性的初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们的定义顺序调用)
  2. 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按他们的定义顺序调用)、
  3. 调用构造器
package JAVA面向对象高级部分.static_.codeBlock;

public class CodeBlockDetail02 {
    public static void main(String[] args) {
        //System.out.println(A1.number);
        /**
         * 返回值是:
         * 我是getNumber()的静态方法
         * 我是A1的静态代码块
         * 100
         */
        A1 a1 = new A1();
        /**
         * 返回值:
         * 我是getNumber()的静态方法
         * 我是A1的静态代码块
         * 我是getSum()非静态方法
         * 我是A1类的非静态代码块
         * 我是A1的构造器,初始化最后!!!
         */

    }
}

class A1 {
    //非静态属性初始化
    public int sum = getSum();

    //静态属性的初始化
    public static int number = getNumber();

    //非静态属性初始化
    public int getSum(){
        System.out.println("我是getSum()非静态方法");
        return 200;
    }

    //非静态代码块
    {
        System.out.println("我是A1类的非静态代码块");
    }

    //静态代码块
    static {
        System.out.println("我是A1的静态代码块");
    }

    public static int getNumber(){
        System.out.println("我是getNumber()的静态方法");
        return 100;
    }
    public A1(){
        System.out.println("我是A1的构造器,初始化最后!!!");
    }
}

细节3:(记住)

构造器前面隐含的super关键和调用普通代码块(顺序是super关键字到普通代码块),创建对象的入口是构造器,构造器前面隐含的super和普通代码块决定了执行的顺序

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

package JAVA面向对象高级部分.static_.codeBlock;

public class CodeBlockDetail03 {
    public static void main(String[] args) {
        Cat cat = new Cat();//创建对象的入口是从构造器的
        /**
         * 返回值:
         * 我是Animal类的非静态代码块
         * 我是Animal类的无参构造器
         * 我是Cat类的非静态代码块
         * 我是Cat类的无参构造器
         */
    }
}

/**
 * 构造器的最前面其实隐含了super()和调用本类普通代码块,静态相关的代码块,
 * 属性初始化,在类加载时,就执行完毕了,因此是优先于构造器和普通代码块的执行
 */
class Animal {
    {
        System.out.println("我是Animal类的非静态代码块");
    }
    //Animal类的无参构造器
    public Animal(){
        //这里隐含了
        super();//调用父类的无参构造器
        //这里还隐含了调用本类的非静态代码块
        System.out.println("我是Animal类的无参构造器");
    }
}

class Cat extends Animal{
    {
        System.out.println("我是Cat类的非静态代码块");
    }

    public Cat(){
        //这里隐含了
        super();//调用父类的无参构造器
        //这是还隐含了调用本类的非静态代码块
        System.out.println("我是Cat类的非静态代码块");
    }
}

细节4(记住)(必须理解下面的代码)

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

  1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行):注意没有初始化静态方法因为静态是需要调用才会执行
  2. 子类的静态代码块和静态属性(优先级一新,按定义顺序执行):注意没有初始化静态方法因为静态是需要调用才会执行
  3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行):注意没有初始化静态方法因为静态是需要调用才会执行
  4. 父类的构造器
  5. 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行):注意没有初始化静态方法因为静态是需要调用才会执行
  6. 子类的构造器

继承关系的执行顺序:(1)父类的静态代码块和静态属性的初始化,子类的静态代码块和静态属性的初始化(2)父类普通代码块和普通属性的初始化到父类的构造器 (3)子类普通代码块和普通属性初始化到子类的构造器

父子静态 --》 父类普通 --》父类构造器 --》子类普通 --》子类构造器

小结:在继承关系下,创建对象分两个大步:

第一大步是:先加载父类和子类信息

  1. 先加载父类的静态代码块和静态属性初始化:注意没有初始化静态方法因为静态方法是需要调用才会执行
  2. 再加载子类的静态代码块和静态属性初始化:注意没有初始化静态方法因为静态方法是需要调用才会执行

第二大步是:再创建子类对象,创建对象的入口是从构造器开始,构造器前面默认调用 父类(使用super关键字)代码块和普通属性的初始化

  1. 父类的普通代码块和普通属性初始化:注意没有初始化静态方法因为静态是需要调用才会执行
  2. 父类的构造器
  3. 子类的普通代码块和普通属性初始化:注意没有初始化静态方法因为静态是需要调用才会执行
  4. 子类的构造器

静态方法是调用时才会被执行的

细节5:

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

package JAVA面向对象高级部分.static_.codeBlock;

public class CodeBlockDetail04 {
    public static void main(String[] args) {
        //1.先进行父类的加载
        //2.再创建对象,是从子类的构造器开始的
        new Student();
        /**
         * 返回值
         * 我是Person类一个getVal01方法
         * 我是Person类一个静态代码块
         * 我是Student类的getVal03方法
         * 我是Student类的静态代码块
         * 我是Person类一个getVal02方法
         * 我是Person类一个普通代码块
         * 我是Person类的无参构造器
         * 我是Student类的getVal04方法
         * 我是Student类的非静态代码块
         * 我是Student类的无参构造器
         */
    }
}

class Person {
    //注意是静态方法是调用才会被执行的
    private static int n1 = getVal01();
    public int n2 = getVal02();

    static {
        System.out.println("我是Person类一个静态代码块");//(2)
    }

    {
        System.out.println("我是Person类一个普通代码块");//(6)
    }

    public static int getVal01(){
        System.out.println("我是Person类一个getVal01方法");//(1)
        return 10;
    }

    public int getVal02(){
        System.out.println("我是Person类一个getVal02方法");//(5)
        return 20;
    }
    //构造器
    public Person(){
        //1.隐含了super()
        //2.隐含了普通代码和普通属性的初始化
        System.out.println("我是Person类的无参构造器");//(7)
    }
}

class Student extends Person {
    private static int n3 = getVal03();
    public int n4 = getVal04();

    static {
        System.out.println("我是Student类的静态代码块");//(4)
    }

    {
        System.out.println("我是Student类的非静态代码块");//(9)
    }

    public static int getVal03(){
        System.out.println("我是Student类的getVal03方法");//(3)
        return 30;
    }

    public int getVal04(){
        System.out.println("我是Student类的getVal04方法");//(8)
        return 40;
    }

    public Student(){
        //1.这里隐含了super()语句
        //2.还普通代码块和普通属性的初始化
        System.out.println("我是Student类的无参构造器");
    }
}

练习:

class Person {
	public static int total;
	static {
		total = 100;
		System.out.println("in static block!");
	}
}

public cals Test{
	public static void main(String[] args){
		System.out.println("total="+Person.total);
		System.out.println("total="+Person.total);
	}
}

/**
 *返回值:
 * in static block!
 * total=100
 * total=100
 */

练习2

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

class Test{
	Sample sam1 = new Sample("sam1成员初始化");
	static Sample sam = new Sample("静态成员sam初始化");
	static {
		System.out.println("static块执行");
		if(sam == null)
		System.out.println("sam is null");
    }
		Test(){
			System.out.println("Test默认构造器被调用");
		}
}

public static void main(String[] str[]){
	Test a = new Test();
}

/**
 * 返回值:
 *  静态成员sam初始化
 * static块执行了
 * sam1成员初始化
 * Test默认构造函数被调用
 

对象创建步骤:

  1. 加载类的信息(类信息的加载会倒致静态代码块和静态属性的初始化,加载类信息的三种方式:1.创建对象 2.创建子类对象(父类的类信息也会加载)3.静态属性或静态方法的调用)
  2. 在堆中开辟空间,并对属性初始化(构造器的调用会调用super语句和普通代码块的执行)
  3. 将堆中的地址赋给方法区中的引用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值