加载过程(初始化)
直接看例子:
class A {
static {
System.out.println("A的static块");
}
public static D d = new D();
{
System.out.println("A的非static块");
}
public A() {
System.out.println("A的构造函数");
}
}
class B extends A {
public B() {
System.out.println("B 构造函数");
}
static {
System.out.println("B的static");
}
{
System.out.println("B的非static");
}
}
class C extends B{
{
System.out.println("C的非static");
}
public C() {
System.out.println("C 构造函数");
}
static {
System.out.println("C的static");
}
}
class D {
static {
System.out.println("D的static");
}
{
System.out.println("D的非static");
}
public D() {
System.out.println("D 构造函数");
}
}
public class Test {
public static void main(String[] args) {
A a = new C();
}
}
执行结果:
A的static块
D的static
D的非static
D 构造函数
B的static
C的static
A的非static块
A的构造函数
B的非static
B 构造函数
C的非static
C 构造函数
总结:
1.所有类都会优先加载基类
2.静态成员的初始化优先
3.静态成员的初始化和静态块的执行发生在类加载的时候
4.非static块执行比构造函数早,顺序为(父类非static块-父类构造函数-子类非static块-子类构造函数)
构造函数执行顺序
class A {
public A() {
System.out.println("A的构造函数");
}
}
class B extends A {
public B() {
System.out.println("B 构造函数");
}
}
class C extends B{
private D d1 = new D();
{
System.out.println("C非static块");
}
public C() {
System.out.println("C 构造函数");
}
private D d2 = new D();
}
class D {
public D() {
System.out.println("D 构造函数");
}
}
public class Test {
public static void main(String[] args) {
A a = new C();
}
}
执行结果:
A的构造函数
B 构造函数
D 构造函数
C非static块
D 构造函数
C 构造函数
结论:
1.优先度(父类构造函数>成员构造函数>子类构造函数)
2.非静态成员和非静态块之间执行按照代码顺序来,都比构造函数早
访问静态量(常量/变量)
1.访问子类的静态变量
class A {
static {
System.out.println("A static");
}
public A() {
System.out.println("A的构造函数");
}
}
class B extends A {
static {
System.out.println("B static");
}
public B() {
System.out.println("B 构造函数");
}
public static String b = "Hello";
}
public class Test {
public static void main(String[] args) {
System.out.println(B.b);
}
}
输出:
A static
B static
Hello
结论:访问子类的静态变量会加载父类和子类本身
2.通过子类访问父类静态变量
class A {
public static String a = "World";
static {
System.out.println("A static");
}
public A() {
System.out.println("A的构造函数");
}
}
class B extends A {
static {
System.out.println("B static");
}
public B() {
System.out.println("B 构造函数");
}
public static String b = "Hello";
}
public class Test{
public static void main(String[] args) {
System.out.println(B.a);
}
}
输出:
A static
World
结论:通过子类访问父类的静态变量只会加载父类,不会加载子类
3.通过子类访问静态常量
class A {
public static final String a = "World";
static {
System.out.println("A static");
}
}
class B extends A {
static {
System.out.println("B static");
}
public static final String b = "Hello";
}
public class Test{
public static void main(String[] args) {
System.out.println(B.a);
System.out.println(B.b);
}
}
输出:
World
Hello
结论:访问静态常量不会导致类的初始化,在连接过程中初始化(准备阶段)