2009-11-07 29 views
18

Tôi tình cờ gặp một mã Java tại nơi làm việc của tôi. Đây là kịch bản: Có 2 lớp - ClassAClassB.biến cố định chung tĩnh trong một lớp java đã nhập

ClassA không có gì ngoại trừ 4 giá trị chuỗi cuối cùng tĩnh công khai bên trong nó. Mục đích của nó là sử dụng những giá trị như ClassA.variable (đừng hỏi tôi tại sao, nó không phải là mã của tôi).

ClassB nhập ClassA. Tôi đã chỉnh sửa các giá trị chuỗi trong ClassA và biên dịch nó. Khi tôi chạy ClassB tôi có thể thấy nó đang sử dụng các giá trị cũ - không phải là giá trị mới. Tôi đã phải biên dịch lại ClassB để làm cho nó sử dụng các giá trị mới từ ClassA! (Tôi đã phải biên dịch lại các lớp khác nhập ClassA!)

Đây có phải là do JDK 1.6 hoặc tôi nên biết trước đó để biên dịch lại ClassB cũng! Soi sáng cho tôi. :)

Trả lời

23

Nếu giá trị của các biến số final từ lớp ClassA xảy ra là hằng số biên dịch, trình biên dịch có thể đã đặt chúng vào các lớp bằng cách sử dụng ClassA thay vì tạo tham chiếu thời gian chạy. Tôi nghĩ, đây là những gì đã xảy ra trong trường hợp bạn mô tả.

Ví dụ:

public class Flags { 
    public static final int FOO = 1; 
    public static final int BAR = 2; 
} 

public class Consumer { 
    public static void main(String[] args) { 
     System.out.println(Flags.FOO); 
    } 
} 

Trong ví dụ này, trình biên dịch sẽ có khả năng kết hợp các giá trị của FOO vào mã được tạo cho Consumer thay vì tạo ra các tài liệu tham khảo thời gian chạy tương đương. Nếu giá trị của FOO thay đổi sau này, bạn sẽ phải biên dịch lại Consumer để sử dụng giá trị mới.

Đây là một tối ưu hóa, có một số lợi thế về hiệu quả và tốc độ của chương trình được biên soạn. Ví dụ, nội tuyến giá trị có thể cho phép tối ưu hóa hơn nữa trong các biểu thức, trong đó sử dụng nó, ví dụ:

int x = Flags.FOO * 10; 

Trong ví dụ này, nội tuyến giá trị (ở đây: 1) cho phép trình biên dịch để ý, rằng làm cho nhân không có sự khác biệt, và có thể được bỏ qua alltogether.

+1

vì vậy, bạn đang nói kết quả tĩnh công khai là hằng số thời gian biên dịch? không biết điều đó. nghĩ rằng đó chỉ là một hằng số và không thể sửa đổi trong thời gian chạy! Cảm ơn bạn đã giúp đỡ. –

+3

Anwser tốt. Nếu bạn muốn thấy rằng biến đang được inlined, bạn có thể sử dụng javap để xem cách lớp được biên dịch, ví dụ: "javap -c Flags". –

3

Đó là sự cố tương thích nhị phân. Tham chiếu đến các trường liên tục được giải quyết tại thời gian biên dịch. Hành vi bạn đang thấy là chính xác; nếu bạn thay đổi các giá trị trong lớp A thì bạn sẽ phải biên dịch lại máy khách (lớp B). Để tránh các vấn đề như vậy, hãy xem xét thêm các hằng số bằng cách sử dụng một kiểu enum, được giới thiệu trong bản phát hành Java 5.0.

2

Tại sao bạn cố gắng biên dịch riêng từng lớp?

Sử dụng hệ thống xây dựng như maven hoặc kiến ​​hoặc chỉ để cho IDE của bạn làm điều đó.

Điều duy nhất cần làm là biên dịch lại mọi java phụ thuộc vào lớp java đã thay đổi cho đến khi mọi lớp có thể được thực hiện đã được biên dịch lại.

+0

Một hoặc các lớp học khác có thể không nằm trong tầm kiểm soát của bạn. – DJClayworth

2

Nếu bạn không sử dụng các giá trị trong một công tắc bạn có thể làm điều này thay vì:

public class A 
{ 
    public static final int FOO; 
    public static final String BAR; 

    static 
    { 
     FOO = 42; 
     BAR = "Hello, World!"; 
    } 
} 

sau đó trình biên dịch sẽ không còn cứng mã hóa các giá trị trong các lớp khác mà đang sử dụng chúng.

2

Giả sử ClassA trông như thế này:

public class ClassA { 
    public static final int FOO = 1; 
    public static final int BAR = 2; 
} 

Nếu bạn biên dịch lại nó, ClassB sẽ tiếp tục sử dụng các giá trị cũ. Tôi đoán nó có thể phụ thuộc vào trình biên dịch, nhưng tôi nghĩ rằng đây là hành vi điển hình. Nếu bạn không muốn biên dịch lại ClassB mọi một hằng số trong những thay đổi ClassA, bạn sẽ phải làm một cái gì đó như thế này:

public class ClassA { 
    public static final int FOO = CONST(1); 
    public static final int BAR = CONST(2); 

    public static int CONST(int i) { return i; } 
} 

bởi vì hiện nay javac là không muốn nội tuyến các hằng số. Thay vào đó, nó sẽ gọi phương thức CONST (int) khi bộ khởi tạo tĩnh của ClassA chạy.

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