类初始化过程
- 一个类要创建实例需要先加载并初始化该类
- main方法所在的类需要先加载和初始化
- 一个子类初始化前需要先初始化父类
- 一个类初始化就是执行
<clinit>
()方法 - 由静态类变量显示赋值代码 和静态块组成,按代码顺序执行
<clinit>
()只执行一次
实例初始化过程
- 实例初始化就是执行
<init>()
方法 <init>()
可能重载有多个,有几个构造器就有几个<init>()
方法- ()方法由非静态实例变量显示赋值代码和构造块、构造方法组成
- 非静态实例变量显示赋值代码 和构造块 从上到下按顺序执行,构造方法最后执行
- 每次创建实例对象,调用构造方法,执行的就是
<init>()
方法 <init>()
方法的首行就是super()或super(实参),即执行父类的<init>()
执行顺序
- 父类静态变量和静态块(按代码顺序执行)
- 子类静态变量和静态块(按代码顺序执行)
- 父类非静态实例变量显示赋值代码 和构造块(按代码顺序执行)
- 父类构造方法最后执行,并初始化父类普通成员变量
- 子类非静态实例变量显示赋值代码 和构造块(按代码顺序执行)
- 子类构造方法最后执行,并初始化子类普通成员变量
构造块与静态块
- 静态块:用static申明,JVM加载类时执行,仅执行一次
- 构造块:类中直接用{}定义,每一次创建对象时执行
public class Test {
//静态对象
public static char text = 'a';
//构造函数
public Test() {
System.out.println('c');
}
//构造块
{
System.out.println('b');
}
//静态块
static {
System.out.println(text);
}
public static void main(String[] args) {
Test a = new Test();
}
}
控制台:
a
b
c
执行顺序优先级:静态块>main()>构造块>构造方法
构造块不具有独立执行的能力,编译器会把构造代码块插入到每个构造函数的最前端,构造代码块不是在构造函数之前运行,而是依托于构造函数
然而,这里的静态块,并不是仅仅静态块,而是静态域,包含了静态变量,静态块,这两者的执行顺序就是按照位置顺序进行。
this特殊情况
public class Client {
public static int count = 0;
{
count++;
}
public Client() {
}
public Client(int i) {
this();
}
public Client(String string) {
}
public static void main(String[] args) {
System.out.println(Client.count);
new Client();
System.out.println(Client.count);
new Client(1);
System.out.println(Client.count);
new Client("1");
System.out.println(Client.count);
}
}
控制台
0
1
2
3
new Client(1);
执行时,先调用构造块,再执行this();
,遇到this关键字(也就是构造函数调用自身其他的构造函数时)不插入构造代码块(构造代码块的出现就是为了提取构造函数的共同量,减少各个构造函数的代码而产生的.)
super方法没有任何特殊的地方.编译器只是把构造代码块插入到super方法之后执行而已.
方法的重写
哪些方法不可以被重写
- final
- 静态
- private
对象的多态性
子类重写父类方法,子类对象调用的是子类重写后的方法
非静态方法的默认对象是this,this在构造器(或)表示正在创建的对象
示例
/**
* 父类的初始化<clinit>:
* 1、j = method()
* 2、static {}
* <p>
* 父类的实例化方法:
* 1、super()
* 2、i = test();
* 3、构造块
* 4、构造方法
* <p>
* 非静态方法的前面其实有个默认的对象this,this在构造器(或<init>)表示正在创建的对象
*/
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 ");
}
int test() {
System.out.print("4 ");
return 1;
}
static int method() {
System.out.print("5 ");
return 1;
}
}
/**
* 先初始化父类 5 1
* 再初始化子类<clinit>: 10 6
* 1、j = method()
* 2、static {}
* <p>
* 子类的实例化方法:
* 1、super() 9 3 2
* 2、i = test(); 9
* 3、构造块 8
* 4、构造方法 7
* <p>
* 因为创建两个对象,实例初始化执行两次
*/
public class Son extends Father {
private int i = test();
private static int j = method();
static {
System.out.print("6 ");
}
Son() {
// super(); 写与不写,均会调用父类构造器
System.out.print("7 ");
}
{
System.out.print("8 ");
}
int test() {
System.out.print("9 ");
return 1;
}
static int method() {
System.out.print("10 ");
return 1;
}
public static void main(String[] args) {
Son s1 = new Son();
System.out.println();
Son s2 = new Son();
}
}
console
5 1 10 6 9 3 2 9 8 7
9 3 2 9 8 7