初始化的作用:
-
为类中的成员变量赋值。
- 成员变量:(对于Java中变量不清楚的可以点击这里查看java中变量的介绍)
- (1)静态变量(类变量)
- (2)实例变量
- 成员变量:(对于Java中变量不清楚的可以点击这里查看java中变量的介绍)
初始化分为两种
- (1)类初始化:执行一个叫做<clinit>()类初始化方法 cl = class ,init = initialize
- (2)实例初始化:执行对应的<init>(【…】)实例初始化方法
- 初始化相关的方法不是程序员手动编写的,而是编译器自动组装生成的。
- 类初始化优先于实例初始化
类初始化方法
-
1、为静态变量初始化的。
-
2、类初始化就是执行<clinit>()类初始化方法,这个方法是由编译器组装某些代码而成。它由:
- (1)静态变量的显式赋值语句
- (2)静态代码块
- 两部分组成。至于(1)和(2)谁先执行,看它们声明的先后位置。
-
3、类初始化方法什么时候执行?以及执行的特点?
- (1)当某个类第一次被使用时,这个类会被加载并且初始化。
- 如main方法所在的类,要先完成类初始化,再执行main方法。
- (2)一个类的类初始化方法只会执行一次
- (3)类初始化方法优先于实例初始化方法
- (4)子类初始化时,如果发现父类还没有初始化,会先初始化父类
根据刚才所说,大家可以推一下以下代码的运行结果
- (1)当某个类第一次被使用时,这个类会被加载并且初始化。
public class TestClassInitialize {
public static void main(String[] args) {
ClassInitialize c1 = new ClassInitialize();
ClassInitialize c2 = new ClassInitialize();
ClassInitialize c3 = new ClassInitialize();
ClassInitialize c4 = new ClassInitialize();
ClassInitialize.test();
ClassInitialize.test();
}
}
class ClassInitializeFather{
//静态代码块
static{
System.out.println("父类静态代码块1");
System.out.println("a = " + ClassInitializeFather.a);
//如果在编写代码时,你要先于声明使用,加“类名."
}
private static int a = getA();
private static int b = getB();
static{
System.out.println("父类的静态代码块2");
}
public static int getA(){
System.out.println("父类的getA()");
return 1;
}
public static int getB(){
System.out.println("父类的getB()");
return 2;
}
}
class ClassInitialize extends ClassInitializeFather{
private static int num = getNum();
//静态代码块
static{
System.out.println("子类静态代码块");
}
public ClassInitialize(){
System.out.println("ClassInitialize构造器");
}
/*
* 这里用getNum()方法的返回值,为静态变量num赋值,
* 同时查看这个赋值操作执行的情况。
*/
public static int getNum(){
System.out.println("getNum被执行了");
return 10;
}
public static void test(){
System.out.println("ClassInitialize的静态方法");
}
}
实例初始化方法
-
1、给实例变量赋值
-
2、实例初始化的方法<init>()是由三部分的代码组成:
- (1)非静态变量(实例变量)的显式赋值
- (2)非静态代码块
- (3)构造器
- 并且一个类至少有一个实例初始化方法,也可能很多个,实例初始化方法的个数由构造器的个数决定。
- 其中这三部分来说,(1)和(2)是按顺序组装。(3)构造器中的代码一定是最后。
-
3、什么时候执行?执行的特点是什么?
- (1)你每new一个对象,就会执行一个实例初始化方法。
- 每次调用哪个实例初始化方法,看你调用哪个构造器。
- (2)要执行子类的实例初始化方法,会先执行父类相应的实例初始化方法
根据刚才所说,大家可以推一下以下代码的运行结果
- (1)你每new一个对象,就会执行一个实例初始化方法。
public class TestInstanceInitialize {
public static void main(String[] args) {
new Instance();
//new Instance(2);
}
}
class Fu{
private int a = getA();
{
System.out.println("(1)父类的非静态代码块");
}
public Fu(){
System.out.println("(2)父类无参构造");
}
public Fu(int i){
System.out.println("(3)父类有参构造");
}
public int getA(){
System.out.println("(4)父类getA()");
return 1;
}
}
class Instance extends Fu{
public Instance(){
System.out.println("(5)子类无参构造器");
}
public Instance(int a){
this.a = a;
System.out.println("(6)子类有参构造器");
}
//非静态代码块
{
System.out.println("(7)子类非静态代码块");
}
private int a = getA();
public int getA(){
System.out.println("(8)子类getA()");
return 1;
}
public static void test(){
System.out.println("静态方法");
}
}
类初始化和实例初始化的总结:
-
(1)父类的类初始化
-
(2)子类的类初始化
-
(3)父类的对应的实例初始化
-
(4)子类的对应的实例初始化
-
A:顺序(1)(2)(3)(4)
-
B:其中的(1)(2)只会执行一次;(3)(4)每new一个对象就执行一次。
-
C:子类构造器中如果没有super()或super(实参列表)表示执行的是父类的无参的实例初始化方法<init>()
-
如果子类的构造器中有super()或super(实参列表)表示执行对应的实例初始化方法
-
D:如果在实例初始化过程中,涉及到调用某个方法,那么如果这个方法没有static修饰,要考虑是否被子类重写了。
(如果这个方法有static修饰,不会被重写,在哪个类中,就执行哪个类的) -
类初始化的方法的由两部分组成:
- (1)静态变量的显式赋值
- (2)静态代码块
- 它俩按顺序执行。
-
实例初始化方法由三部分组成:
- (1)非静态变量的显式赋值
- (2)非静态代码块
- (3)构造器
- 其中(1)和(2)按顺序,(3)在最后。但是(3)中的super()或super(实参列表)被组装到实例初始化方法中也在首行。