2009-12-12 36 views
8
class test 
{ 
    test() 
    { 
     System.out.println("Constructor"); 
    } 

    { 
    System.out.println("Hai"); 
    } 

} 
public class sample 
{ 
    public static void main(String [] a) 
    { 
     test t = new test();   
    } 
} 

trong mã ở trên tại sao câu lệnh được đưa ra trong dấu ngoặc đơn ((tức là "Hai") được In trước khi hằng số được thực thi.nghi ngờ về các vấn đề cơ bản về java?

Trả lời

31

Để cho bày tỏ với một ví dụ rõ ràng hơn:

public class Test { 

    static { 
     System.out.println("static initializer"); 
    } 

    { 
     System.out.println("instance initializer"); 
    } 

    public Test() { 
     System.out.println("constructor"); 
    } 

} 

và thử nghiệm nó như sau:

public class Main { 

    public static void main(String[] args) { 
     Test test1 = new Test(); 
     Test test2 = new Test(); 
    } 

} 

đầu ra:

static initializer 
instance initializer 
constructor 
instance initializer 
constructor 

Các initializers tĩnh được thực hiện chỉ lần trong thời gian chạy, đặc biệt trong khi tải lớp. Các trình khởi tạo thể hiện được thực thi trong mọi instantiation trước constructor.

Bạn có thể có nhiều hơn một trong số chúng và chúng sẽ được thực hiện theo thứ tự khi chúng xuất hiện trong mã hóa.

Lợi ích chính của trình khởi tạo mẫu là chúng được thực hiện bất kể bạn tạo hàm tạo nào. Chúng áp dụng cho mỗi người trong số họ để bạn không cần phải lặp lại việc khởi tạo chung trên tất cả chúng.

Lợi ích chính của bộ khởi tạo tĩnh là chúng chỉ được thực thi một lần trong khi tải lớp. Một ví dụ thực tế nổi tiếng là trình điều khiển JDBC. Khi bạn làm

Class.forName("com.example.jdbc.Driver"); 

mà chỉ thực thi static initializers, sau đó bất kỳ (đàng hoàng) điều khiển JDBC sẽ tự đăng ký trong DriverManager như sau

static { 
     DriverManager.registerDriver(new com.example.jdbc.Driver()); 
} 

cách này DriverManager có thể tìm thấy các trình điều khiển JDBC ngay trong getConnection().

5

Có. Đó là một số instance initializer. Nó chạy ngay khi lớp được khởi tạo.

+2

Vì vậy, từ khóa tĩnh là tùy chọn? – blackanchorage

+0

vì vậy nếu tạo một khối tĩnh trong mã trên, mà sẽ chạy đầu tiên các khối tĩnh hoặc khối khởi tạo tĩnh? .... u có thể giải thích những gì là initializer tĩnh? – Hariharbalaji

+1

Nó chắc chắn KHÔNG phải là bộ khởi tạo 'tĩnh'. – BalusC

2

Niềng răng ngay lập tức trong một lớp giới thiệu trình khởi tạo cá thể (được giới thiệu trong Java 1.1). Chúng được xử lý giống như mã để gán các trường được viết như là một phần của khai báo. Vì vậy, sau đây là tương đương:

private final Thing x = new Thing(); 

private final Thing x; 
{ 
    x = new Thing(); 
} 

Mã này được thực hiện bởi nhà xây dựng ngay sau khi gọi một constructor siêu. Vì vậy, giả sử không có khởi động khác, các mã có thể được viết tương đương như một phần của các nhà xây dựng:

private final Thing x; 
public MyCLass() { 
    super(); // Often implicit. 
    x = new Thing(); 
} 

Niềng răng ở vị trí tương đương trước bởi các initialisers static từ khóa và tĩnh, thực hiện một lần khi một lớp được khởi tạo, không phải trên một cơ sở cho từng trường hợp.

3

Trong mã trên, tại sao câu lệnh được đưa ra trong dấu ngoặc đơn ((tức là "Hai") được in trước khi hàm tạo được thực hiện.

Bởi vì đây là hành vi mong đợi như đã mô tả trong phần 12.5 Creation of New Class Instances của Java Language Specification :)

Ngay trước khi một tham chiếu đến đối tượng mới tạo được trả về như kết quả, các nhà xây dựng chỉ là được xử lý để khởi tạo đối tượng mới sử dụng quy trình sau:

  1. Gán arg uments cho hàm tạo để tham số tham số mới được tạo cho hàm tạo này lời gọi.
  2. Nếu constructor này bắt đầu bằng một lời gọi constructor rõ ràng của khác constructor trong cùng một lớp (sử dụng this), sau đó đánh giá luận và quá trình xây dựng gọi đệ quy sử dụng các cùng năm bước. Nếu người xây dựng đó yêu cầu hoàn tất đột ngột, thì quy trình này hoàn tất đột ngột cho cùng một lý do; nếu không, hãy tiếp tục với bước 5.
  3. Hàm khởi tạo này không bắt đầu bằng hàm tạo rõ ràng gọi hàm tạo khác trong cùng một lớp (sử dụng this). Nếu nhà xây dựng này dành cho một lớp khác không phải là Object, thì nhà xây dựng này sẽ bắt đầu bằng cách yêu cầu rõ ràng hoặc ngụ ý yêu cầu một nhà xây dựng siêu lớp (sử dụng super). Đánh giá các đối số và xử lý yêu cầu phân lớp đệ quy hàm tạo đệ quy sử dụng năm bước giống nhau này. Nếu yêu cầu hàm khởi tạo này hoàn thành đột ngột, thì thủ tục này hoàn tất đột ngột vì cùng một lý do . Nếu không, tiếp tục với bước 4.
  4. Execute initializers dụ và ví dụ initializers biến cho lớp này, gán các giá trị của initializers biến dụ cho biến dụ tương ứng, trong thứ tự từ trái sang bên phải trong đó xuất hiện văn bản trong mã nguồn cho lớp học. Nếu việc thực hiện bất kỳ các trình khởi tạo này dẫn đến một ngoại lệ , thì không thêm trình khởi chạy nào được xử lý nữa và thủ tục này hoàn tất đột ngột với trường hợp ngoại lệ đó. Nếu không, tiếp tục với bước 5. (Trong một số đầu triển khai, trình biên dịch sai bỏ qua các mã để khởi tạo một lĩnh vực nếu biểu thức khởi tạo lĩnh vực là một biểu thức hằng số có giá trị tương đương với giá trị khởi tạo mặc định cho loại của nó.)
  5. Thi hành phần còn lại của phần thân của hàm tạo này. Nếu việc thực thi đó hoàn thành đột ngột, thì quy trình này hoàn tất đột ngột vì lý do tương tự. Nếu không, thủ tục này hoàn tất bình thường.

Xem phần 8.6 Instance Initializers để biết thêm chi tiết về ... trình khởi tạo mẫu.