代码块的格式:
(static) {
......
};
分号也可以省略
普通的代码块,即不用static修饰的代码块,在创建对象实例时会被隐式地调用,
且每一次创建,都会被调用,在创建子类对象时,父类中的代码块也会被执行
public class NonStatic {
public static void main(String[] args) {
A a = new A();
B b = new B();
}
}
class A{
{
System.out.println("A的代码块被执行");
}
}
class B extends A{
{
System.out.println("B的代码块被执行");
}
}
运行结果:
A的代码块被执行
A的代码块被执行
B的代码块被执行
静态代码块:
在类加载的时候会被调用,只会执行一次
类什么时候被加载:
1.创建对象实例是(new)
2.创建子类对象实例,父类也会被加载
3.使用类的静态成员时(静态属性,静态方法)
public class NonStatic {
public static void main(String[] args) {
B b = new B();
int num = C.num;
}
}
class A{
static{
System.out.println("A的静态代码块被执行");
}
}
class B extends A{
static{
System.out.println("B的静态代码块被执行");
}
}
class C{
static int num;
static{
System.out.println("C的静态代码块被执行");
}
}
运行结果:
A的静态代码块被执行
B的静态代码块被执行
C的静态代码块被执行
在创建一个对象时,类中的调用顺序是:
(1)先调用静态代码块和静态属性初始化,静态成员之间按照定义先后顺序调用
(2)后调用普通代码块和普通属性初始化,普通成员之间按照定义先后顺序调用
public class demo3 {
public static void main(String[] args) {
D d = new D();
}
}
class D{
private int num1=getnum1();
private static int num2=getnum2();
{
System.out.println("普通代码块");
}
static{
System.out.println("静态代码块");
}
public static int getnum1(){
System.out.println("num1");
return 100;
}
public static int getnum2(){
System.out.println("num2");
return 200;
}
}
运行结果:
num2
静态代码块
num1
普通代码块
构造器中的隐藏内容:
在类的构造器中会隐藏super()和本类普通代码块的调用
public class demo4 {
public static void main(String[] args) {
Y y=new Y();
}
}
class X{
public X(){
//super();
//普通代码块调用
System.out.println("X构造器语句");
}
{
System.out.println("X的代码块");
}
}
class Y extends X{
public Y(){
//super();
//普通代码块调用
System.out.println("Y构造器语句");
}
{
System.out.println("Y的代码块");
}
}
运行结果:
X的代码块
X构造器语句
Y的代码块
Y构造器语句
总结,在创建子类对象时,先后调用顺序如下:
1.父类的静态代码块和静态属性
2.子类的静态代码块和静态属性
3.父类的普通代码块和普通属性初始化
4.父类的构造方法
5.子类的普通代码块和普通属性初始化
6.子类的构造方法
public class summary {
public static void main(String[] args) {
K k = new K();
}
}
class J{
private int num1=getnum1();
{
System.out.println("J的普通代码块");
}
private static int num2=getnum2();
static{
System.out.println("J的静态代码块");
}
public int getnum1(){
System.out.println("J的普通变量初始化");
return 1;
}
public static int getnum2(){
System.out.println("J的静态变量初始化");
return 1;
}
public static void speak(){
System.out.println("Jspeak");
}
public J(){
//super();
//调用普通代码块和普通属性
System.out.println("J的构造方法");
}
}
class K extends J{
private int num3=getnum3();
{
System.out.println("K的普通代码块");
}
private static int num4=getnum4();
static{
System.out.println("K的静态代码块");
}
public int getnum3(){
System.out.println("K的普通变量初始化");
return 1;
}
public static int getnum4(){
System.out.println("K的静态变量初始化");
return 1;
}
public static void speak(){
System.out.println("Kspeak");
}
public K(){
//super();
//调用普通代码块和普通属性
System.out.println("K的构造方法");
}
}
运行结果:
J的静态变量初始化
J的静态代码块
K的静态变量初始化
K的静态代码块
J的普通变量初始化
J的普通代码块
J的构造方法
K的普通变量初始化
K的普通代码块
K的构造方法
在上面的例子中,要创建K的实例,要先加载其父类J,J中的静态成员被加载,然后再加载K的静态成员.
再执行K的构造器,但在K构造器中隐藏了super()和普通代码块和属性调用,因此先执行J的构造器.同理,J的构造器中也隐藏了super()和普通代码块和属性调用.但Object类构造器中没有输出.接着先后调用J的普通变量和普通代码块,再调用J的构造器里的语句,至此K的super()调用完毕.同理依次调用K的普通变量初始化,K的普通代码块,K的构造方法.