1. 程式人生 > >例項化一個類的物件時的執行順序

例項化一個類的物件時的執行順序

下面這個小程式,你能把結果做對嗎? 我就做錯了,對例項化物件時的執行順序有些生疏了,希望以後杜絕類似的疏忽。

--Book.java:

import java.io.IOException;

public class Book {
  Book(int marker) {
    System.out.println("Book(" + marker + ")");
  }
  public void f1(int marker) {
    System.out.println("f1(" + marker + ")");
  }
}


--Room.java:

import java.io.IOException;

public class Room {
  static Book book1 = new Book(1);
  public Room() {
    System.out.println("Room()");
    book2.f1(1);
  }
  public static void f2(int marker) {
    System.out.println("f2(" + marker + ")");
  }
  Book book2 = new Book(2);
}


--Shelf.java:

import java.io.IOException;

public class Shelf {
  Book book3 = new Book(3);
  Book book4 = new Book(4);
  public Shelf() {
    System.out.println("Shelf()");
    book4.f1(2);
  }
  void f3(int marker) {
    System.out.println("f3(" + marker + ")");
  }
  static Book book5 = new Book(5);
}


--InitializationTest.java:

import java.io.IOException;
class InitializationTest {
  public static void main(String[] args) {
    System.out.println("Creating new Shelf() in main");
        Room.f2(1);
        new Shelf();
    System.out.println("Creating new Shelf() in main");
    new Shelf();
    new InitializationTest();
  }
  static Room room = new Room();
   Shelf cupboard = new Shelf();
   InitializationTest()
   {
           System.out.println("InitializationTest()");
   }
}

執行結果是:

Book(1)
Book(2)
Room()
f1(1)
Creating new Shelf() in main
f2(1)
Book(5)
Book(3)
Book(4)
Shelf()
f1(2)
Creating new Shelf() in main
Book(3)
Book(4)
Shelf()
f1(2)
Book(3)
Book(4)
Shelf()
f1(2)
InitializationTest()

仔細看一看上面的流程,可以概括成幾個要點:

1.在例項化一個類的物件時,先要例項化該類的成員變數,再執行該類的建構函式。

2. 在例項化一個類的成員變數時,先要例項化靜態成員變數,再例項化非靜態成員變數。

3. 一個類的靜態成員變數只例項化一次,即只有一個拷貝,在該類的所有物件中共享。

4. 執行一個類的靜態成員函式時,該類的物件並沒有生成,因此,只會例項化該類的靜態成員變數,而不會例項化非靜態成員變數,也不會執行建構函式。

另外,上面4個java檔案都沒有指定包名,可以讓他們在同一個目錄中,這樣在使用“javac”命令編譯檔案以及“java”命令執行檔案時就不需要顯示的指明classpath的路徑。

而如果他們分屬不同的package,比如說Book.java、Room.java、Shelf.java在同一個包com1中, 而InitializationTest.java在另一個包com2中,那麼我們使用“javac”編譯InitializationTest.java時,就要使用-classpath指明com1所在的位置,當然InitializationTest.java要import com1.*.

然後,使用“java”命令來執行InitializationTest.class時,也要用-classpath指明包com2的位置。

因此,使用預設包名和自定義包名來編譯時還是有區別的,只是大家容易忽略罷了。