目录
普通的代码块,在创建对象实例时,会被隐式的调用。每被创建一次,就会调用一次。
6、静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
1、代码块的基本介绍
代码块又称为初始化块,属于类中的成员【即 是类的一部分】,类似于类的方法,将逻辑语句封装在方法体中,通过{}包围起来。
但和方法不同,没有方法名,没有返回值,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建类时隐式调用。
相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作。
场景:如果多个构造器中都有重复的语句,可以将重复部分抽取到代码块中,提高代码的重用性。
例如: 看电影时,我们要打开荧幕,再播放广告,等时间到了在播放正片,每播放新的一部影片时,我们都要重复打开荧幕和播放广告这个动作,我们就可以提出来放在代码块中,这样每次创建对象时,就会优先执行代码块中的内容。
public class CodeBook {
public static void main(String[] args) {
Movie movie = new Movie("银河补习班");
System.out.println("=============");
Movie movie1 = new Movie("人生大事");
}
}
class Movie{
private String name;
{
System.out.println("电影荧幕打开");
System.out.println("播放广告");
}
public Movie(String name) {
this.name = name;
System.out.println("电影"+name+"正在播放");
}
}
运行结果
2、静态代码块
static代码块叫静态代码块,作用是对类进行初始化它随着类的加载进行初始化,而且随着类的加载而被执行并且只会执行一次。
如果是普通代码块,每次创建一个对象就执行一次。
类什么时候加载【重点】
-
创建对象实例时(new)
public class TestC { public static void main(String[] args) { //1、创建对象实例时(new) new AAA(); } } class AAA{ static{ System.out.println("AAA的静态代码块被调用"); } }
-
创建子类对象实例时,父类也会被加载
public class TestC { public static void main(String[] args) { //2、创建子类对象实例时,父类也会被加载,而且父类先被加载,子类后被加载 new BBB(); } } class BBB extends AAA{ static{ System.out.println("BBB的静态代码块被调用"); } } class AAA{ static{ System.out.println("AAA的静态代码块被调用"); } }
创建子类对象实例时,父类也会被创建,而且父类先被加载,子类后被加载。
-
使用类的静态成员时(静态属性,静态方法)
public class TestC { public static void main(String[] args) { //3、使用类的静态成员时(静态属性,静态方法) System.out.println(CCC.n); } } class CCC{ public static int n=99; static{ System.out.println("CCC的静态代码块被调用"); } }
3、代码块的使用小细节
普通的代码块,在创建对象实例时,会被隐式的调用。每被创建一次,就会调用一次。
public class TestC {
public static void main(String[] args) {
DDD ddd = new DDD();
DDD ddd1 = new DDD();
DDD ddd2 = new DDD();
}
}
class DDD{
static{
System.out.println("DDD的静态代码块被调用");
}
{
System.out.println("DDD的普通代码块被调用");
}
}
静态代码块只在类加载时创建且只创建一次,而普通代码块每创建一次对象就调用一次。
如果只是使用类的静态成员时,普通代码块并不会执行。
public class TestC {
public static void main(String[] args) {
System.out.println(DDD.n2);
}
}
class DDD{
public static int n2=88;//静态属性
static{//静态代码块
System.out.println("DDD的静态代码块被调用");
}
{//普通代码块
System.out.println("DDD的普通代码块被调用");
}
}
直接调用类的静态属性,导致类加载,静态代码块被调用。
只加载类,未创建对象,普通代码块不会被调用。
1、static代码块时类加载时执行,只会执行一次
2、普通代码块是在创建对象时调用的,创建一次,调用一次
4、创建一个对象时,在一个类中的调用顺序
- 静态代码块和静态属性的初始化(注意:静态代码块和静态属性初始化调用的优先级相同,如有多个静态代码块和静态属性,按定义的顺序调用)
- 调用普通代码块和普通属性,优先级和静态代码块一样(同上)
- 调用构造方法。
public class TestD { public static void main(String[] args) { D d=new D(); } } class D{ public D() { System.out.println("D的无参构造器被调用"); } { System.out.println("普通代码块被调用"); } private int n2 = getn2(); private static int n1=getn1(); static{ System.out.println("D的静态代码块被调用"); } public static int getn1(){ System.out.println("getn1被调用"); return 100; } public int getn2(){ System.out.println("getn2被调用"); return 99; } }
大家可以先思考下上方的代码的输出顺序为什么。
5、存在继承关系时,类中的调用顺序
- 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
- 父类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
- 父类的构造方法
- 子类的普通代码块和普通属性的初始化(优先级一样,按定义顺序执行)
- 子类的构造方法
public class TestD { public static void main(String[] args) { D d=new D(); } } class D extends E{ public D() { System.out.println("子类D的无参构造器被调用"); } { System.out.println("子类D的普通代码块被调用"); } private int n2 = getn2(); private static int n1=getn1(); static{ System.out.println("子类D的静态代码块被调用"); } public static int getn1(){ System.out.println("子类getn1被调用"); return 100; } public int getn2(){ System.out.println("子类getn2被调用"); return 99; } } class E{ public E() { System.out.println("父类E的无参构造器被调用"); } { System.out.println("父类E的普通代码块被调用"); } private int n2 = getn4(); private static int n1=getn3(); static{ System.out.println("父类E的静态代码块被调用"); } public static int getn3(){ System.out.println("父类的getn3被调用"); return 100; } public int getn4(){ System.out.println("父类的getn4被调用"); return 99; } }
6、静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员
class F{
private int n1=66;
private static int n2 = 55;
private void m1(){
}
private static void m2(){
}
static {
//静态代码块只能调用静态成员
//System.out.println(n1);//直接报错
System.out.println(n2);//ok
//m1();//报错,提示不能调用非静态方法
m2();//ok
}
{//普通代码块可以调用任何成员
System.out.println(n1);
System.out.println(n2);
m1();
m2();
}
}