2012-10-17 25 views
5

Đây là đoạn mã bằng ngôn ngữ Java:phân nhánh mà không thể được nhìn thấy bởi trình biên dịch

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

if(value <= 9) 
o = 8; 

System.out.println(o); 
} 

Tại sao biên dịch không thể nhìn thấy thứ hai nếu tuyên bố xem xét các lựa chọn cuối cùng của giá trị? Nó sẽ không biên dịch. Trân trọng

+3

Lỗi là: biến o có thể chưa được khởi tạo (System.out.println (o)) –

+2

Tại sao có hai câu lệnh if thay vì if..else? – CBredlow

+0

Tôi chỉ khám phá langue. Không có lý do đặc biệt nào cho hai câu lệnh if. – uml

Trả lời

5

Trình biên dịch phải đối xử value như thay đổi trừ khi bạn nói ngược lại. Tuyên bố nó finalfixes the problem:

public void name(){ 
    final int value = 9; 
    int o; 
    if(value > 9) o = 5; 
    if(value <= 9) o = 8; 
    System.out.println(o); 
} 
+0

Tôi ngạc nhiên vì nó không thể dễ dàng phỏng đoán rằng nó không thay đổi trong trường hợp này –

+1

@BrianAgnew Tôi chỉ có thể đoán rằng trình biên dịch không được phép xử lý hai lần đọc 'giá trị' trong hai' if's khi truy cập giống nhau giá trị (và do đó làm cho hai điều kiện bổ sung). – dasblinkenlight

+1

Trình biên dịch chỉ có thể hoạt động trên các biểu thức liên tục khi kiểm tra để gán phân định. Cả 'giá trị> 9' và' giá trị <= 9' đều là các biểu thức không đổi trừ khi 'value' là biến cố định, về cơ bản là biến' final'. – pingw33n

0

Trong biên soạn:

Trình biên dịch thấy rằng bạn đã không được khởi tạo biến 'o' và bạn đang in trong sysout.

bạn có thể đạt được điều này:

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

else 
o = 8; 

System.out.println(o); 
} 
0

Initialize o trước nếu phát biểu sau khi bạn khai báo nó

o=0; 
0

Theo JLS (§16) mỗi biến và không trống trường địa phương phải được chắc chắn giao trước khi nó có thể được đã sử dụng. Trình biên dịch thực hiện một số phân tích tĩnh cơ bản để đảm bảo nó.

Ý tưởng đằng sau gán rõ ràng là gán cho biến cục bộ hoặc trường cuối trống phải xuất hiện trên mọi đường dẫn thực thi có thể truy cập. Tương tự như vậy, ý tưởng đằng sau việc bỏ gán không xác định là không có phép gán nào khác cho biến cuối cùng trống được phép xảy ra trên bất kỳ đường dẫn thực hiện có thể nào cho một phép gán.

Máy phân tích tĩnh chỉ có thể suy ra các giá trị của biểu thức không đổi ($15.28) không phải là trường hợp trong ví dụ của bạn.

1

Lý do phiên bản gốc không biên dịch là quy tắc "xác định rõ ràng" của JLS trong JLS section 16 nói rằng o chưa được gán rõ ràng. Trình biên dịch báo cáo điều này với một thông điệp bí ẩn nói rằng "o có thể chưa được khởi tạo".

Bây giờ, bất kỳ ai có kỹ năng suy luận đơn giản đều có thể thấy rằng điều kiện thứ 2 if là phủ định của điều kiện if đầu tiên và do đó biến trên thực tế luôn được khởi tạo. Tuy nhiên, JLS không cho phép trình biên dịch thực hiện việc khấu trừ đó. JLS cho biết đây là lỗi ...

Có một số cách để khắc phục sự cố này. Ví dụ:

  • Gán điều gì đó cho o trong tuyên bố.
  • Thay thế hai câu lệnh if bằng một tuyên bố if/else duy nhất.
  • Khai báo valuefinal.

Sửa chữa cuối cùng là thú vị.Lý do nó hoạt động là các quy tắc gán xác định JLS yêu cầu trình biên dịch để lấy giá trị của biểu thức boolean hằng số có giá trị biên dịch vào tài khoản.

Tuyên bố này (với final thêm)

final int value = 9; 

nghĩa là value là một hằng số thời gian biên dịch. Điều đó có nghĩa là value <= 9value > 9 cũng là hằng số biên dịch. Do đó, JLS quy tắc phân định rõ rằng o chắc chắn giao sau

if(value <= 9) o = 8; 

và có thể được sử dụng sau này mà không có một lỗi biên dịch.


Các quy tắc phân công rõ ràng được thiết kế để ngăn chặn việc sử dụng các biến chưa được khởi tạo, và ngăn chặn trống final biến được khởi tạo nhiều hơn một lần.

Việc xử lý thận trọng các giá trị biểu thức của JLS trong các quy tắc gán cố định được thiết kế để tránh các vấn đề trong đó trình biên dịch Java suy ra rằng một cái gì đó chắc chắn được gán. Subcase của các biểu thức biên dịch-thời gian-hằng số có thể được xử lý bằng cách đơn giản đánh giá biểu thức, và các quy tắc JLS ngầm nhận ra điều này.

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