1.楔子
java中的初始化块是一个不常用但是非常使用的语法,其中也有一些易错的点,这里对一些点进行澄清。
2. Java中初始化块
在Java中,有两种初始化块:静态初始化块
和非静态初始化块
。它们都是定义在类中,用大括号{}括起来,静态代码块在大括号外还要加上static关键字。
2.1 非静态初始化块(构造代码块):
作用:
给对象进行初始化。对象一建立就运行,且优先于构造函数的运行 。
与构造函数的区别:
非静态初始化块给所有对象进行统一初始化,构造函数只给对应对象初始化。
应用:
将所有构造函数共性的东西定义在构造代码块中。
- 对于普通的类而言,可以放在初始化块中的初始化工作其实完全可以放到构造函数中进行,只不过有时会带来些许不便,如有多个构造器,就要在多个地方加上初始化函数完成初始化工作,而如果放到初始化块中的话则只要写一次即可。
- 但是,如果只是这一点便利的话,还不足以使用初始化块,其实初始化块真正体现其独一无二的作用是在匿名内部类中,由于是匿名内部类,因而无法写构造方法,但是很多时候还是要完成相应的初始化工作,这时就需要用到初始化块了,特别是Android中大量地使用匿名内部类,初始化块的作用就十分突出
2.2静态初始化块
作用:
给类进行初始化。随着类的加载而执行,且只执行一次
与构造代码块的区别:
- 1)构造代码块用于初始化对象,每创建一个对象就会被执行一次;静态代码块用于初始化类,随着类的加载而执行,不管创建几个对象,都只执行一次。
- 2)静态代码块优先于构造代码块的执行
- 3)都定义在类中,一个带static关键字,一个不带static
比如可以记录第一次访问类的日志,或方便单例模式的初始化等。对于单例模式,可以先用static块初始化一些可能还被其他类访问的基础参数,等到真正需要加载大量资源的时候(getInstance)再构造单体,在构造函数中加载资源。
其实初始化块就是构造器的补充,初始化块是不能接收任何参数的,定义的一些所有对象共有的属性、方法等内容时就可以用初始化块初始化了。
2.3执行顺序
构造函数、非静态初始化块、静态代码块都是用于初始化,三者的执行顺序依次是:静态代码块>构造代码块>构造函数
。
静态初始化块的作用就是当JVM在装载类时,你想让它做一些事情,那么,就可以用静态初始化块。这几者的执行顺序是:
- (JVM在装载类时)先装载类的静态成员,再执行静态初始化块(同样,当一个类有继承自某类时,则会先装载该父类,那么,父类的装载或执行顺序,也都如句子所述)。
- (在创建类的实例时)先执行实例初始化块,再执行构造方法;但对于一棵继承树中,会先调用父类的构造方法,那么其执行顺序也如句子所述。
所有的静态初始化块都优先执行,其次才是非静态的初始化块和构造函数,它们的执行顺序是:
父类的静态初始化块
子类的静态初始化块
父类的初始化块
父类的构造函数
子类的初始化块
子类的构造函数
实例演示:
父类
package com.sino.daily.code_2019_3_30;
import com.google.common.base.MoreObjects;
/**
* Created on 2019/3/30 10:26.
*
* @author caogu
*/
public class Book {
private static String defaultName;
private String name;
static {
defaultName = "default book";
System.out.println("default book");
}
{
name = "book name";
System.out.println("book name");
}
public Book() {
System.out.println("Book Nll Constructor");
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("name", name)
.toString();
}
}
子类:
package com.sino.daily.code_2019_3_30;
import com.google.common.base.MoreObjects;
/**
* Created on 2019/3/30 10:32.
*
* @author caogu
*/
public class JavaBook extends Book {
private static String defaultNum;
private Integer num;
static {
defaultNum = "100";
System.out.println("100");
}
{
num = 2;
System.out.println("2");
}
public JavaBook() {
System.out.println("JavaBook Nll Constructor");
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("num", num)
.toString();
}
}
测试代码:
public static void main(String[] args) {
JavaBook javaBook = new JavaBook();
System.out.println(javaBook);
}
结果: