代码块注意
1.在一个类里,初始化执行优先级:父类静态属性 = 父类静态代码块 > 子类静态属性 = 子类静态方法 > 父类普通语句块 = 父类普通属性 > 父类构造器 >子类普通语句块 = 子类普通属性 > 子类构造器,
2.static代码块作用是对类进行初始化,只能直接调用静态成员,随着类的加载而执行,且只会执行一次(因为类加载也只会加载一次),而普通代码块,则是每创建一个对象就执行一次
ps:类在什么时候会被加载?①创建对象时(new) ②子类创建对象时,父类的信息也会被加载 ③使用类的静态成员时(使用类的静态成员,不会用到普通代码块)
在使用类的静态属性时,会按照静态语句块和静态属性定义的顺序来作为执行顺序,普通成员和普通代码块之间也是如此,一句话总结就是:静态属性和静态语句块运行优先级一样,普通代码块和普通属性运行优先级一样,看如下代码
public class Test { public static void main(String[] args) { System.out.println(ReadKeyBoard.a); } } class ReadKeyBoard { public static int a = Value();//如果静态变量初始化用返回值,那这个方法要是静态方法
//因为静态属性是类加载的时候就初始化的,普通方法这时根本就还没创建 public int b = 3; public ReadKeyBoard(int a) { this.a = a; System.out.println("构造器"); } static { System.out.println("静态代码块" + a);//如果这里读不出a的值,证明静态代码块比静态属性更早执行 }
{
System.out.println("普通代码块" + b );
}
public int value(){
System.out.println("value");
return 10;
}//当b初始化时输出value
public static int Value(){
System.out.println("VALUE");//当c初始化时输出VALUE
return 100;
}
}
运行结果为
VALUE
静态代码块100
value
普通代码块10
构造器
而把静态变量和静态语句块定义顺序调换,则会报错
class ReadKeyBoard { static { System.out.println("静态代码块" + a);//这里编译器提示非法前向引用,
//因为这时是先执行静态语句块,静态属性还没初始化 } public static int a;
public ReadKeyBoard(int a) {
this.a = a;
System.out.println("构造器");
}
{
System.out.println("普通代码块" + b );//这里编译器提示非法前向引用,
//因为这时是先执行普通语句块,普通属性还没初始化
}
public int b = 3;
}
3.构造器最前面隐含的不仅是super()还有调用普通代码块,没有静态代码块是因为静态代码块是在类加载的时候就执行的,所以就像第二条说的一样--------优先级很高,并且只执行一次,
而有时在还没加载过类信息时,你创建对象,调用了构造器,他会执行,让你误以为构造器里有调用静态语句块,其实是没有的。
如下代码
public class Test { public static void main(String[] args) throws Exception{ System.out.println(ReadKeyBoard.a);//静态0,0 System.out.println("============="); new aa();//由于已经加载过类,所以不会再有静态语句块的执行 } } class ReadKeyBoard { public static int a ; public int b ; public ReadKeyBoard() { System.out.println("构造器" ); } { System.out.println("普通代码块" + b ); } static { System.out.println("静态代码块" + a); } } class aa extends ReadKeyBoard{ public aa() { System.out.println("子类构造器"); } }
运行结果
静态代码块0 0 ============= 普通代码块0 构造器 子类构造器