2011年11月16日 星期三

[Java] Object Initialization - (2)

Initialization and inheritance
  • When an object is initialized, all the instance variables defined in the object's class must be set to proper initial values.
  • When an object is created, the Java virtual machine allocates enough space for all the object's instance variables, which include all fields defined in the object's class and in all its superclasses.
    • The data that must be allocated on the heap
    • The actual manner of representing objects on the heap is an implementation detail of each particular Java virtual machine.
  • Object will have no fields in any given Java platform implementation.
    • Because Object is the superclass of all other objects, any fields declared in Object must be allocated for every object used by every Java program.

A note on the word "inherit"
  • A class's members are the fields and methods that
    • Actually declared in the class
    • Inherits from superclasses.
      • Only inherits accessible members of its superclasses. (the subclass doesn't override or hide those accessible members.)

Initializing fields in superclasses
  • Unlike methods, constructors are never inherited.
  • If you don't explicitly declare a constructor in a class
    • Will not inherit a constructor from its direct superclass.
    • The compiler will generate a default constructor
      • This is because a superclass constructor can't initialize fields in the subclass. A subclass must have its own constructor to initialize its own instance variables.
    • => Every class has at least one method responsible for initializing the class variables explicitly declared in that class.
  • To fully initialize an object, the Java virtual machine must invoke (at least) one instance initialization method from each class along the object's inheritance path.

Order of initialization
  • The fields of an object are initialized
    • Starting with the fields declared in the base class.
    • Ending with the fields declared in the object's class.
  • The order of initialization of fields would be:
    • Object's fields (this will be quick, because there are none)
    • ParentClass's fields
    • ChildClass's fields
  • This base-class-first order
    • Aims to prevent fields from being used before they are initialized to their proper (not default) values.
    • In a child constructor or initializer
      • You can safely use a superclass's field directly
      • Call a method that uses a superclass's field.
    • By the time the code in your child constructor or initializer is executed
      • You can be certain that the fields declared in any superclasses have already been properly initialized.

The structure of <init>

  • How does Java ensure the correct ordering of initialization?
    • The Java compiler generates the instance initialization method.
    • Into each <init> method, the compiler can place three kinds of code:
      • An invocation of another constructor
      • Instance variable initializers
      • The constructor body
    • The order in which the compiler places these components into the method determines the order of initialization of an object's fields.



(Almost) every constructor's first act and Automatic invocation of super() (For every class except Object)
  • The first thing each <init> method will do is invoke another constructor.
  • The first statement in a constructor
    • If is this()
      • The corresponding <init> method will start by calling another <init> method of the same class.
    • If not the this()
      • The method for that constructor will begin with an invocation of a superclass constructor.
    • super()
      • You can explicitly invoke a superclass constructor using the super() statement.
      • If you don't, the compiler will automatically generate an invocation of the superclass's no-arg constructor.
        • This is true for default constructors as well.
        • With the exception of class Object, the method for any default constructor will do only one thing: invoke the method for the superclass's no-arg constructor.

Invoking super() with arguments

  • If you want to invoke a superclass constructor that takes parameters,
    • You must provide an explicit super() invocation.
  • If parent class explicitly declares a constructor,
    • The Java compiler won't generate a default constructor. 
  • If a subclass's direct superclass does not offer a no-arg constructor,
    • Eevery constructor in that subclass must begin with either an explicit super() or this()invocation.


Only one constructor invocation allowed

  • You can't have both this() and super() in the same constructor.
    • Can only have one or the other (or neither, if the direct superclass includes a no-arg constructor). 
    • If a constructor includes a this() or super() invocation, it must be the first statement in the constructor.


Catching exceptions not allowed

  • One other rule enforced on constructors is that you can't catch any exceptions thrown by the constructor invoked with this() or super().
  • To do so, you would have to begin your constructor with a try statement.
  • If any instance initialization method completes abruptly by throwing an exception, initialization of the object fails.
    • This in turn means that object creation fails, because in Java programs, objects must be properly initialized before they are used.


When you instantiate a new Child object with the new operator, the JVM will

  1. Allocate (at least) enough space on the heap to hold all the instance variables declared in Child object and its superclasses.
  2. Initialize all the instance variables to their default initial values.
  3. Invoke the method in the Child class.

this() won't change the order of initialization
  • The code for constructor invocations and constructor bodies, the Java compiler also places code for any initializers in the <init> method. 
  • If a class includes initializers, the code for them will be placed after the superclass method invocation but before the code for the constructor body, in every <init> method that begins with an explicit or implicit super() invocation.
  • Code for initializers are not included as part of <init> methods that begin with a this() invocation
  • The initializers for a class are guaranteed to be run only once for each new class creation.


Steps for new operator
  1. 分配空間並且設為 default value。
  2. Child 會先呼叫其 Parent。
  3. Parent 會呼叫 Object。
  4. Object 不會做啥事便回傳。
  5. Parent 初始欄位為你所設定的初始值、constructor,回傳。
    • Note:
      • If <init> in a superclass invokes a method that has been overridden in a subclass, the subclass's implementation of that method will run.
      • If the subclass's method implementation uses instance variables explicitly declared in the subclass, those variables will still have their default initial values.
      • 如果在步驟中呼叫了定義在 child 中的 fields,則會取到它的 default value,因為 Child 並還未經過 <init>
  6. Child 初始欄位為你所設定的初始值、constructor。
  7. JVM 回傳 Child object reference。


Summary
  • 在 java 中有個 implicit 初始動作: initializers,其 method name is <init>,負責執行你所給的預設值 (="initial value")。
  • 初始化的動作是往上優先的(會一直跑到 class Object),然後再依 top-down 的順序,這樣可以確保當 child object 使用到 parent object 時,fields 已經被初始化完成。
    • 因此有繼承關係時,一定會呼叫 super(),不論你是否有寫,super() 也必寫在第一行。
    • class Object 中沒有任何 fields,因為 Object 是每個 object 的 superclass。
  • <init> 的執行時間會在 superclass constructor 後,以及 child class constructor body 前。
  • If B extends A
    • allocate spaces and set default values for A and B -> call super() in B -> execute A's <init> -> execute A's constructor -> execute B's <init> -> execute B's constructor -> return B's reference to new operator.
    • 對 A 而言,B 裡 fields 都是不可視的,即使是 B 覆寫了 A's member。



* Reference
- Object Initialization in Java ***

沒有留言:

張貼留言