Java中有代码块分为4种:普通代码块、构造断码块、静态代码快、同步代码块。
普通代码块指的就是一般方法中的花括号的代码段。
构造代码块就是在类中,不属于任何方法的代码段(当然是在花括号内)。
静态代码块就是在类中,不属于任何方法的代码段,并且“{”的前面有static。
同步代码块用在线程间。
package JLearner.codeblock;
public class Parent {
{
//构造代码快
System.out.println("Parent' Block");
}
static{
//静态代码快
System.out.println("Parent' Static Block");
}
public Parent() {
System.out.println("Parent' Constructor");
}
public static void StaticMethod()
{
System.out.println("Parent' StaticMethod");
}
}
package JLearner.codeblock;
public class Child extends Parent {
{
//构造代码快
System.out.println("Child' Block");
}
static{
//静态代码快
System.out.println("Child' Static Block");
}
public Child() {
System.out.println("Child' Constructor");
}
public static void StaticMethod()
{
System.out.println("Child' StaticMethod");
}
}
下面的各个部分分别执行,即保证是程序第一次调用。
执行效果即输出在注释里,总结也看注释
package JLearner.codeblock;
public class RunTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
//每当生成子类的对象时,它的加载顺序值得记住它:
//首先是执行所有静态代码块,先是父类的,然后是子类的
//接下来是非静态部分(构造)
//然后执行父类的构造代码块,之后是父类的构造方法(即构造代码块在构造函数之前被执行)
//然后执行子类的构造代码块,最后是子类的构造方法
// new Child();
/*
Parent' Static Block
Child' Static Block
Parent' Block
Parent' Constructor
Child' Block
Child' Constructor
*/
//当调用子类的静态方法时,父类和子类都是要加载的,所以两个类的静态代码块被首先调用
//之后直接调用子类本身的静态方法
//注意:只是调用类的静态方法,而不生成对象的话,构造代码块不会被执行
// Child.StaticMethod();
/*
Parent' Static Block
Child' Static Block
Child' StaticMethod
*/
//调用父类类似
// Parent.StaticMethod();
/*
Parent' Static Block
Parent' StaticMethod
*/
//连续生成两个子类对象,可以发现:
//静态代码块只会在程序运行第一次加载相应或者相关(如父子关系)的类时才会被调用
//也就是说静态代码块只会被调用一次
//而构造代码块则是每次生成对象时都会被调用
// new Child();
// new Child();
/*
Parent' Static Block
Child' Static Block
Parent' Block
Parent' Constructor
Child' Block
Child' Constructor
Parent' Block
Parent' Constructor
Child' Block
Child' Constructor
*/
//那么怎么算是加载类呢?即什么样的操作被认为是第一次加载类呢?
//这里做了另外2个实验。
//之前的new操作(生成对象),毫无疑问,将对对象所对应的类以及其对应的父类(或者父类的父类。。。)进行加载
//注意:而 “类名.class”是不会加载类的。
//从下面的例子可以看到:
//静态代码块没有被执行
//System.out.println(Child.class.toString());
/*
class JLearner.codeblock.Child
*/
//而使用Class.forName是会加载类的,也就是说,使用Class.forName可能执行类的静态代码块
// try {
// Class.forName("JLearner.codeblock.Child");
// } catch (ClassNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
/*
Parent' Static Block
Child' Static Block
*/
}
}