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成员被访问时加载的。



相关文章推荐

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

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

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

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

Thinking in Java 构造器的调用顺序

//: polymorphism/Sandwich.java // Order of constructor calls. package polymorphism; import static ne...

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

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

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

Java中,类内部变量初始化先后顺序问题。在类内部,变量定义的先后顺序决定了初始化的顺序。 /***************************************************...

Thinking in java -- set和存储顺序

先运行一下代码,package containers;//: containers/TypesForSets.java // Methods necessary to put your own typ...

Thinking in Java 第二章 一切都是对象

本人是汕头大学学生,现读大三。 在大二的时候就开始学习android,但是要学习好android,必须要学好java,于是我在那时候就开始学习java了。 在读完一本java简单入门后,开始一边学习a...

【Thinking in Java】一:对象导论

对象导论 1抽象过程 对象具有状态、行为和标识。每一个对象都可以拥有内部数据(例如:轮子的直径,宽度)、方法(它们产生行为),并且每一个对象都可以惟一地与其他对象区分开来,就是指每一个对象在内存中都有...

第2章 一切都是对象——Thinking-in-Java

第2章 一切都是对象“尽管以C++为基础,但Java是一种更纯粹的面向对象程序设计语言”。 无论C++还是Java都属于杂合语言。但在Java中,设计者觉得这种杂合并不象在C++里那么重要。杂合语言...
  • oftoo
  • oftoo
  • 2016年03月24日 18:35
  • 192

Thinking in Java 第11章 持有对象(容器)

//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社– 使用泛型容器:ArrayList apples = new ArrayList(); 可以在编译期防止将错误类型的对象放置到容器中...
  • jia1410
  • jia1410
  • 2016年07月07日 14:15
  • 177
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Thinking in Java:对象初始化顺序
举报原因:
原因补充:

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