在Java语言中,当初始化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象
一、Java程序的初始化一般遵循3个原则(优先级依次递减):
- 静态对象(变量)优先于非静态对象(变量)初始化,其中静态对象(变量)只初始化一次,而非静态对象(变量)可能会初始化多次。
- 父类优先于子类进行初始化。
- 按照成员变量的定义顺序进行初始化。即使变量定义散步与方法定义之中,它们依然在任何方法(包括构造函数)被调用之前先初始化。
二、Java程序初始化在许多不同代码块中来完成时,它们的执行顺序依次如下:
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
父类非静态变量
父类非静态代码块
父类构造函数
子类非静态变量
子类非静态代码块
子类构造函数
验证代码如下:
public class Base {
static {
System.out.println("Base父类静态代码块");
}
{
System.out.println("Base父类非静态代码块");
}
public Base(){
System.out.println("Base父类构造函数");
}
}
public class Derived extends Base {
static {
System.out.println("Derived子类静态代码块");
}
{
System.out.println("Derived子类非静态代码块");
}
public Derived(){
System.out.println("Derived子类构造函数");
}
public static void main(String[] args) {
System.out.println("执行main方法");
new Derived();
}
}
输出结果为:
Base父类静态代码块
Derived子类静态代码块
执行main方法
Base父类非静态代码块
Base父类构造函数
Derived子类非静态代码块
Derived子类构造函数
例子二:
/**
*父类的初始化<client>
* (1) j=method();
* (2) 父类的静态代码块
*
* 父类的实例化方法:
* (1)super()(最前) object类了,略过
* (2)i=test(); 这里i=test()执行的是子类重写的test()方法
* (3)父类的非静态代码块
* (4)父类的无参构造(最后)
*
* 非静态方法前面其实有一个默认的对象this
* this在构造器(或<init>)它表示的是正在创建的对象,因为这里是在创建son对象,所以test()执行的是子类重写的代码(面向对象多态)
*/
public class Father {
private int i=test(); //父类非静态变量
private static int j=method(); //父类静态变量
static { //父类静态代码块
System.out.print("(1)");
}
Father(){ //父类构造器
System.out.print("(2)");
}
{ //父类非静态代码块
System.out.print("(3)");
}
private int test() {
System.out.print("(4)");
return 1;
}
private static int method() {
System.out.print("(5)");
return 1;
}
}
/**
* 类初始化过程:
* 1、一个类要创建实例需要先加载并初始化该类
* main方法所在的类需要先加载和初始化
*
* 2、一个子类要初始化需要先初始化父类
*
* 3、一个类初始化就是执行<client>()方法
* <client>()方法由静态类变量显示赋值代码和静态代码块组成
* 类变量显示赋值代码和静态代码块代码从上到下顺序执行
* <client>()方法只执行一次
*
*
* 实例初始化过程:
* 实例初始化就是执行<init>()方法
* <init>()方法可能重载有多个,有几个构造器就有几个<init>方法
* <init>()方法由非静态实例变量显示赋值代码和非静态代码块、对应构造器代码组成
* 非静态实例变量显示赋值代码和非静态代码块代码从上到下顺序执行,而对应构造器的代码最后执行
* 每次创建实例对象,调用对应构造器,执行的就是对应的<init>方法
* <init>方法的首行是super()或super(实例列表),即对应父类的<init>方法
*
* 方法的重写Override:
* 1、哪些方法不可以被重写
* final方法
* 静态方法
* private等子类中不可见方法
* 2、对象的多态性
* 子类如果重写了父类的方法,通过子类对象调用的一定是子类重写过的代码
* 非静态方法默认的调用对象是this
* this对象在构造器或者说<init>方法中就是正在创建的对象
*
* 执行顺序:
* 先初始父类:(5)(1)
* 初始化子类:(10)(6)
*
* 子类的实实例化方法<init>:
* (1)super()(最前) (9)(3)(2)
* (2)i=test(); (9)
* (3)子类的非静态代码块 (8)
* (4)子类的无参构造(最后) (7)
*/
public class Son extends Father{
private int i=test(); //子类非静态变量
private static int j=method(); //子类静态变量
static { //子类静态代码块
System.out.print("(6)");
}
Son(){ //子类构造器
System.out.print("(7)");
}
{ //子类非静态代码块
System.out.print("(8)");
}
public int test(){
System.out.print("(9)");
return 1;
}
public static int method(){
System.out.print("(10)");
return 1;
}
public static void main(String[] args) {
Son son=new Son();
System.out.println();
Son son1=new Son();
}
}
运行结果:
(5)(1)(10)(6)(4)(3)(2)(9)(8)(7)
(4)(3)(2)(9)(8)(7)