10.代码块快速入门
代码块是加载类时,或创建对象时隐式调用
代码块理解:
-
相当于另外一种形式的构造器,可以做初始化操作
-
如果多个构造器中都有重复语句,可以抽取到初始化块中,提高代码的重用性
-
实例:
public class HelloJava { public static void main(String[] args) { Movie movie1 = new Movie("钢铁侠"); Movie movie2 = new Movie("唐人街探案3",100); Movie movie3 = new Movie("唐人街探案3",100,"陈思成"); } } class Movie{ private String name; private double price; private String director; //3个构造器 -> 重载 //(1)下面三个构造器都有相同的语句 //(2)代码看起来比较冗余 //(3)这时可以把相同的语句都放到代码块里 //(4)这样不管用那个构造器,创建对象,都会先调用代码块的内容 //(5)代码块调用的顺序优先于构造器 { System.out.println("电影屏幕打开..."); System.out.println("广告开始了..."); System.out.println("电影正式开始..."); } public Movie(String name) { this.name = name; System.out.println("Movie(String name)被调用..."); } public Movie(String name, double price) { this.name = name; this.price = price; System.out.println("Movie(String name, double price)被调用..."); } 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)被调用..."); } }
11*.代码块使用细节
-
static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象,就执行
-
类什么时候被加载(类加载的三种情况,非常重要)
1.创建对象实例时(new)
2.创建子类对象实例时,父类也会被加载(继承的本质:先加载父类再加载子类)
3.使用类的静态成员时(静态属性,静态方法)
public class HelloJava { public static void main(String[] args) { //类加载的情况举例 //1.创建对象实例时(new) //AA aa = new AA(); //2.创建子类对象实例时,父类也会被加载 //AA aa2 = new AA(); //3.使用类的静态成员时(静态属性,静态方法) System.out.println(Cat.n1); } } class Cat{ public static int n1 = 999;//静态属性 static { System.out.println("Cat 的静态代码块被执行..."); } } class BB{ //静态代码块 static { System.out.println("BB 的静态代码块1被执行..."); } } class AA extends BB{ //静态代码块 static { System.out.println("AA 的静态代码块1被执行..."); } }
-
普通的代码块,再创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。如果只是使用类的静态成员时,普通代码块并不会执行(注意:与类加载无关)
-
创建一个对象时,在一个类 调用顺序是:(重点,难点)
1.调用静态代码块和静态属性的初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果又多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用
public class HelloJava { public static void main(String[] args) { A a = new A();//(1)getN1被调用(2)静态代码块被调用 } } class A{ //静态属性初始化 private static int n1 = getN1(); //静态代码块 static { System.out.println("静态代码块被调用..."); } //静态方法 public static int getN1(){ System.out.println("getN1被调用..."); return 100; } }
2.调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果又多个普通代码块和多个普通属性初始化,则按定义顺序调用)
3.调用构造方法
-
构造器的最前面其实隐含了super()和 调用普通代码块。但静态相关的代码块,属性初始化,在类加载时,就执行完毕了,因此是优先于 构造器和普通代码块执行的
class A{ //构造器 public A(){ //这里有隐藏的执行要求 //(1)super(); //(2)调用本类的普通代码块 System.out.println("ok") } }
-
创建一个子类时,他们的静态代码,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1.父类的静态代码块和静态属性
2.子类的静态代码块和静态属性
3.父类的普通代码块和普通属性初始化
4.父类的构造方法
5.子类的普通代码块和普通属性初始化
6.子类的构造方法
-
静态代码块只能调用静态成员,普通代码块可以调用任意成员
12.代码块练习题
Q1:下面的代码输出什么
A1:(1) "in static block!" (2)total = 100 (3)total = 100
Q2:下面代码输出什么
A2:(1)"静态成员sam初始化" (2)"static块执行" (3)"sam1成员初始化" (4)"Test默认构造函数被调用"