Thinking in Java:对象初始化顺序

原创 2013年12月04日 17:30:52

P131

《一》初始化的顺序是先静态对象(如果它们尚未因前面的对象创建过程而被初始化),而后是“非静态”对象。从输出结果中可以观察到这一点。要执行main()(静态方法),必须加载StaticInitialization类,然后其静态域table和cupboard被初始化,这将导致它们对应的类也被加载,并且由于它们也都包含静态的Bowl对象,因此Bowl随后也被加载。这样,在这个特殊的程序中的所有类在main()开始之前就都被加载了。实际情况通常并非如此,因为在典型的程序中,不像在本例中所做的那样,将所有的事物都通过static联系起来。总结一下对象的创建过程,假设有个名为Dog的类:

1.即使没有显式地使用static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。

2.然后载入Dog.class(后面会学到,这将创建一个Class对象),有关静态初始化的所有操作都会执行。因此,静态初始化只在Class对象首次加载的时候执行一次。

3.当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。

4.这块存储空间会被清零,这就自动地将对象中多有的基本类型数据都设置成默认值(对数字来说就是0,对布尔型和字符型也相同),而引用则被设置成了null.

5.执行所有出现于字段定义处的初始化动作。

6.执行构造器。

//: initialization/StaticInitialization.java
// Specifying initial values in a class definition.
import static net.mindview.util.Print.*;

class Bowl {
  Bowl(int marker) {
    print("Bowl(" + marker + ")");
  }
  void f1(int marker) {
    print("f1(" + marker + ")");
  }
}

class Table {
  static Bowl bowl1 = new Bowl(1);
  Table() {
    print("Table()");
    bowl2.f1(1);
  }
  void f2(int marker) {
    print("f2(" + marker + ")");
  }
  static Bowl bowl2 = new Bowl(2);
}

class Cupboard {
  Bowl bowl3 = new Bowl(3);
  static Bowl bowl4 = new Bowl(4);
  Cupboard() {
    print("Cupboard()");
    bowl4.f1(2);
  }
  void f3(int marker) {
    print("f3(" + marker + ")");
  }
  static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {
  public static void main(String[] args) {
    print("Creating new Cupboard() in main");
    new Cupboard();
    print("Creating new Cupboard() in main");
    new Cupboard();
    table.f2(1);
    cupboard.f3(1);
  }
  static Table table = new Table();
  static Cupboard cupboard = new Cupboard();
} /* Output:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
*///:~

(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的

  1.为父类的静态属性分配空间并赋于初值

  1.执行父类静态初始化块;

(2)加载子类

  2.为子类的静态属性分配空间并赋于初值

  2.执行子类的静态的内容;

(3)加载父类构造器

  3.初始化父类的非静态属性并赋于初值

  3.执行父类的非静态代码块;

  4.执行父类的构造方法;

(4)加载子类构造器

  5.初始化子类的非静态属性并赋于初值

  5.执行子类的非静态代码块;

  6.执行子类的构造方法.

总之一句话,静态代码块内容先执行(父先后子),接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。



《二》显式的静态初始化

Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(有时也叫做"静态块")。就像下面这样:

//: initialization/Spoon.java
public class Spoon {
  static int i;
  static {
    i = 47;
  }
} ///:~

尽管上面的代码看起来像个方法,但它实际只是一段跟在static关键字后面的代码。与其他静态初始化动作一样,这段代码仅执行一次:当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即使从未生成过那个类的对象)。

静态代码块和静态变量根据初始化顺序来决定谁先执行!

构造器也是static方法,尽管static关键字并没有显式写出来。因此更准确地讲,类是在其任何static成员被访问时加载的。



Java基础总结之类与对象的初始化顺序

Java
  • crazyf2015
  • crazyf2015
  • 2015年06月27日 21:51
  • 2157

Java 对象初始化顺序 执行顺序

先看一道Java面试题: 求这段程序的输出。   解答此题关键在于理解和掌握类的加载过程以及子类继承父类后,重写方法的调用问题:   从程序的执行顺序去解答: 1.编译;当这个类被编译...
  • Zhangxichao100
  • Zhangxichao100
  • 2015年10月14日 22:59
  • 1577

C++中关于全局对象的初始化顺序

在stackoverflow上看到下面这样一个问题: 这个问题很简单,意思就是两个全局不同类的instance,其中一个依赖另一个,怎么确保他们的构造顺序。也就是说O2依...
  • fuliangcheng1985
  • fuliangcheng1985
  • 2014年01月03日 15:42
  • 1424

《Thinking in Java》——静态、非静态成员变量、子句的初始化顺序(含继承)及对象创建过程

初始化顺序1.静态成员变量或子句只有在首次new该类对象或者首次访问该类成员变量或方法时被执行一次; 2.非静态成员变量或子句在每次new该类对象时都会初始化; 3.构造器在成员变量和子句初始化之...
  • qq_31217423
  • qq_31217423
  • 2017年05月06日 17:27
  • 211

【Thinking in Java真题精选】1. 类的初始化顺序

本题出自《Think in Java》第5章,主要考验对类初始化的理解,轻微烧脑,挑战一下吧~...
  • get_set
  • get_set
  • 2016年07月16日 22:55
  • 254

Thinking in java 读书笔记(四、toString,class的初始化顺序)

一、 当编译器需要一个String,而只有对象的时候,自动调用toString方法 二、 子类的构造器类型数量一定是在父类构造器之内 三、 简易的代理 四、 final 五、 初始化...
  • nimahai_balabala
  • nimahai_balabala
  • 2017年11月15日 14:55
  • 69

Thinking in java 之:静态数据的初始化及初始化顺序

无论创建了多少个对象,静态数据都只占用一份存储区域,static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值,如...
  • qq_17864929
  • qq_17864929
  • 2015年09月06日 10:40
  • 243

【Thinking in Java真题精选】2. 存在继承关系时的类加载顺序

本题出自《Think in Java》第8章,主要考验在存在继承关系时的类加载顺序
  • get_set
  • get_set
  • 2016年07月17日 16:07
  • 354

Thinking in Java之类内部变量定义先后顺序

Java中,类内部变量初始化先后顺序问题。在类内部,变量定义的先后顺序决定了初始化的顺序。 /***************************************************...
  • gg543012991
  • gg543012991
  • 2016年07月19日 10:15
  • 306

Thinking in java -- set和存储顺序

先运行一下代码,package containers;//: containers/TypesForSets.java // Methods necessary to put your own typ...
  • u010926176
  • u010926176
  • 2015年03月31日 11:26
  • 775
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Thinking in Java:对象初始化顺序
举报原因:
原因补充:

(最多只允许输入30个字)