2012-01-31 15 views
24

Tài liệu ngôn ngữ Java nói "Nếu kiểu nguyên thủy hoặc chuỗi được định nghĩa là hằng số và giá trị được biết tại thời gian biên dịch, trình biên dịch sẽ thay thế tên hằng số ở mọi nơi trong mã với giá trị của nó. được gọi là hằng số biên dịch. "Hằng số thời gian biên dịch và biến

Vì vậy, sự hiểu biết của tôi là nếu chúng ta có một đoạn mã:

private final int x = 10; 

Sau đó, trình biên dịch sẽ thay thế tất cả các lần xuất hiện của 'x' trong mã với nghĩa đen '10'. Nhưng nói giả sử hằng số được khởi tạo với giá trị tại thời gian chạy,

private final int x = getX(); // here getX() returns an integer value at run-time. 

Sẽ có bất cứ thả hiệu suất (nào có thể xảy không đáng kể) nó có thể được so sánh với thời gian biên dịch liên tục?

câu hỏi khác là liệu dòng dưới mã:

private int y = 10; // here y is not final 

được xử lý trong cùng một cách như thời gian biên dịch liên tục bởi trình biên dịch?

EDIT: Cuối cùng, những gì tôi hiểu từ câu trả lời là:

  1. final static phương tiện thời gian biên dịch liên tục
  2. chỉ final nghĩa của nó một hằng số nhưng được khởi tạo tại thời gian chạy
  3. chỉ static có nghĩa là được khởi tạo vào thời gian chạy
  4. mà không cần final là một biến và sẽ không được coi là không đổi.

là sự hiểu biết của tôi đúng chưa?

+5

về điểm 2. Bạn sai rồi! cuối cùng int a = 1; a là hằng số thời gian biên dịch. cuối cùng int b; b = 1; b không phải là – landry

Trả lời

41

Compile thời gian liên tục phải:

  • tuyên bố chính thức
  • nguyên thủy hoặc String
  • khởi tạo trong khai
  • khởi tạo với biểu thức hằng

Vì vậy private final int x = getX(); phải là không đổi .

Đối với câu hỏi thứ hai private int y = 10; không phải là không đổi (không phải cuối cùng trong trường hợp này), vì vậy trình tối ưu hóa không thể chắc chắn rằng giá trị sẽ không thay đổi trong tương lai. Vì vậy, nó không thể tối ưu hóa nó tốt như giá trị không đổi. Câu trả lời là: Không, nó không được xử lý theo cách tương tự như hằng số thời gian biên dịch.

+2

JLS xác định cụm từ không đổi: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 –

+1

một ví dụ khác để xóa sự nghi ngờ: final int a = 1; là một hằng số biên dịch thời gian nhưng cuối cùng int a; a = 2; không phải là –

+0

tôi nghĩ rằng nó có thể được khởi tạo trong vòng khai báo hoặc trong constuctor –

1

thể là một thực sự nhỏ giọt hiệu suất trên một số máy cho private final int x = getX(); vì đó sẽ bao gồm ít nhất một cuộc gọi phương thức (ngoài thực tế rằng đây không phải là một thời gian biên dịch không đổi) nhưng khi bạn cho biết, nó sẽ là không đáng kể vậy tại sao phải bận tâm?

Đối với câu hỏi thứ hai: y không phải là cuối cùng và do đó không phải là hằng số thời gian biên dịch, vì nó có thể thay đổi khi chạy.

1

private final int x = getX(); Sẽ được gọi là lần đầu tiên đối tượng của bạn được khai báo. Hiệu suất "thả" sẽ phụ thuộc vào getX() nhưng đó không phải là loại điều để tạo ra một số nút cổ chai.

2

Từ khóa final có nghĩa là biến sẽ được khởi tạo một lần và chỉ một lần. Một hằng số thực sự cần phải được khai báo là static. Vì vậy, không có ví dụ nào của bạn được xử lý như hằng số bởi trình biên dịch. Tuy nhiên, từ khóa cuối cùng cho bạn biết (và trình biên dịch) rằng các biến của bạn sẽ được khởi tạo một lần duy nhất (trong hàm tạo hoặc theo nghĩa đen). Nếu bạn cần giá trị của chúng được gán vào thời gian biên dịch, các trường của bạn phải tĩnh.

Hiệu suất không thực sự bị ảnh hưởng, nhưng hãy nhớ rằng các kiểu nguyên thủy là bất biến, một khi bạn đã tạo nó sẽ giữ giá trị đó trong bộ nhớ cho đến khi bộ gom rác loại bỏ nó. Vì vậy, nếu bạn có một biến y = 1; và sau đó bạn thay đổi nó thành y = 2; trong bộ nhớ JVM sẽ có cả hai giá trị, nhưng biến của bạn sẽ "trỏ" vào giá trị sau.

private int y = 10; // đây y không phải là cuối cùng

được xử lý theo cách tương tự như thời gian biên dịch không đổi bởi trình biên dịch?

No. Đây là biến thể hiện, được tạo, được khởi tạo được sử dụng khi chạy.

0

Theo JLS, không có yêu cầu "biến cố định" phải tĩnh.

Vì vậy, "biến cố định" có thể là tĩnh hoặc không tĩnh (biến mẫu).

Nhưng JLS áp đặt một số yêu cầu khác đối với một biến trở thành một "biến cố" (bên cạnh việc chỉ chính thức):

  • là chỉ String hoặc nguyên thủy
  • khởi inline chỉ, bởi vì nó là cuối cùng, và trống thức không được phép
  • khởi tạo với "biểu hiện liên tục" = "thời gian biên dịch biểu thức hằng" (xem JLS quote dưới đây)

4.12.4. final Variables (JLS)

Một liên tục biến là một biến cuối cùng của kiểu nguyên thủy hoặc kiểu String được khởi tạo với một biểu thức hằng (§15.28).

15.28. Constant Expressions

Một thời gian biên dịch thường xuyên biểu là một biểu thức biểu thị một giá trị kiểu nguyên thủy hoặc một String mà không hoàn thành đột ngột và là gồm chỉ sử dụng như sau:

Các loại nguyên thủy và chữ cái của loại Chuỗi (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

Sử dụng các kiểu nguyên thủy và phôi để nhập Chuỗi (§15.16)

Toán tử đơn nguyên +, -, ~, và! (Nhưng không ++ hoặc -) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

Các nhà khai thác chất nhân *, /, và% (§15.17)

Các nhà khai thác phụ gia + và - (§15.18)

Các nhà khai thác dịch chuyển < <, >>, và >>> (§15.19)

Các toán tử quan hệ <, < =,>, và> = (nhưng không phải ví dụ) (§15.20)

Nhà khai thác bình đẳng == và! = (§15.21)

Các toán tử bitwise và logic &,^và | (§15.22)

Điều kiện và toán tử & & và toán tử điều kiện hoặc điều kiện || (§15.23, §15.24)

Toán tử điều kiện bậc ba? : (§15.25)

Biểu thức được lồng tiếng (§15.8.5) có biểu thức được chứa là biểu thức liên tục .

Tên đơn giản (§6.5.6.1) tham chiếu đến các biến không đổi (§4.12.4).

Tên đủ điều kiện (§6.5.6.2) của biểu mẫu TypeName. Mã định danh tham chiếu đến các biến không đổi (§4.12.4).