2014-07-24 39 views
14
class abc { 
    int a = 0; 
    static int b; 
    static abc h = new abc(); //line 4 

    public abc() { 
     System.out.println("cons"); 
    } 

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

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

public class ques { 
    public static void main(String[] args) { 
     System.out.println(new abc().a); 
    } 
} 

Khi tôi viết mã này tôi nhận được đầu ra trong trật tự như thế này:Tạo đối tượng sử dụng từ khóa tĩnh trong Java

ini 
cons 
stat 
ini 
cons 
0 

đây khi tôi tạo ra một đối tượng mới trong main(), class abc đã nạp và static biến và khối được thực hiện theo thứ tự chúng được viết. Khi điều khiển đến dòng 4 static abc h = new abc(); Chặn khởi tạo thể hiện được gọi. Tại sao? tại sao khối tĩnh không được gọi khi một đối tượng mới được tạo ra ở dòng 4 và cho đến khi khối tĩnh đó cũng không được gọi ngay cả một lần, do đó, theo quy ước, khối tĩnh nên được gọi. Tại sao đầu ra không mong đợi này đến?

+1

bản sao có thể có của [Khởi tạo lớp tĩnh Java] (http://stackoverflow.com/questions/3499214/java-static-class-initialization) – DavidPostill

+0

Mã tĩnh chỉ chạy một lần để khi đối tượng thứ hai được tạo (bên trong đầu tiên) nó không được thực hiện. Tôi ngạc nhiên rằng 'ini' được thực hiện vào thời điểm này. – Eypros

+2

@ DavidPostill- Tagged post xóa khái niệm rằng cách khởi tạo tĩnh thường xảy ra. Nhưng nguyên nhân chính của tôi là tại sao khối tĩnh không được gọi ở dòng 4 và thay vào đó khối khởi tạo Instance được gọi. –

Trả lời

6

Khởi tạo trường tĩnh và các khối tĩnh được thực hiện theo thứ tự chúng được khai báo. Trong trường hợp của bạn, mã tương đương với điều này sau khi tách khai báo và khởi tạo:

class abc{ 
    int a; 
    static int b; 
    static abc h;//line 4 

    static { 
     h = new abc();//line 4 (split) 
     System.out.println("stat"); 
    } 

    public abc() { 
     a = 0; 
     System.out.println("ini"); 
     System.out.println("cons"); 
    } 
} 

public class ques{ 
    public static void main(String[] args) { 
     System.out.println(new abc().a); 
    } 
} 

Vì vậy khi bạn đạt đến dòng 4 từ mã của bạn, khởi tạo tĩnh thực sự đang được thực hiện và chưa hoàn thành. Do đó constructor của bạn được gọi trước khi stat có thể được in.

7

JLS says:

Các initializers tĩnh và initializers biến lớp được thực hiện theo thứ tự văn bản, và có thể không đề cập đến các biến lớp được khai báo trong lớp có tờ khai xuất hiện textually sau khi sử dụng, mặc dù các biến lớp này nằm trong phạm vi (§8.3.2.3). Hạn chế này là được thiết kế để phát hiện, tại thời gian biên dịch, hầu hết thông tư hoặc cách khác khởi tạo không đúng định dạng.

Trường hợp này chính xác là trường hợp của bạn.

Dưới đây là ví dụ ban đầu của bạn: http://ideone.com/pIevbX - initializer tĩnh của abc đi sau dụ tĩnh của abc được gán - initializer nên tĩnh có thể không được thực hiện - đó là bản văn sau khi khởi tạo biến tĩnh

Hãy di chuyển dòng 4 sau khối khởi tạo tĩnh - http://ideone.com/Em7nC1:

class abc{ 
int a = 0; 
static int b; 
public abc() { 
    System.out.println("cons"); 
} 
{ 
    System.out.println("ini"); 
} 
static { 
    System.out.println("stat"); 
} 
static abc h = new abc();//former line 4 

} 

Bây giờ bạn sẽ nhìn thấy kết quả như sau:

stat 
ini 
cons 
ini 
cons 
0 

Thứ tự khởi tạo giống như bạn mong đợi - lần đầu tiên được gọi là trình khởi tạo tĩnh và sau đó là phiên bản tĩnh của abc được khởi tạo theo cách thông thường.

Các vấn đề liên quan