2012-11-28 23 views
49

Bởi vì tôi tin rằng đó là một thực hành lập trình tốt, tôi làm cho tất cả các biến (cục bộ hoặc thể hiện) final nếu chúng chỉ được viết một lần.Bài tập biến cuối cùng với try/catch

Tuy nhiên, tôi nhận thấy rằng khi một giao biến có thể ném một ngoại lệ bạn không thể làm cho biết biến thức:

final int x; 
try { 
    x = Integer.parseInt("someinput"); 
} 
catch(NumberFormatException e) { 
    x = 42; // Compiler error: The final local variable x may already have been assigned 
} 

Có cách nào để làm điều này mà không cần đến một biến tạm thời? (hoặc đây không phải là địa điểm phù hợp cho công cụ sửa đổi cuối cùng?)

+1

Tôi nghi ngờ bạn có thể làm điều này mà không có biến tạm thời. – NPE

+8

'cuối cùng int x = makeX();' chắc chắn. (try-catch in function) –

+2

Gây sốc rằng JDK [vẫn không có 'tryParse'] (http://stackoverflow.com/questions/1486077/java-good-way-to-encapsulate-integer-parseint) . –

Trả lời

44

Một cách để làm điều này là giới thiệu biến tạm thời (không final), nhưng bạn đã nói bạn không muốn làm điều đó.

Một cách khác là để di chuyển tất cả các chi nhánh của các mã vào một chức năng:

final int x = getValue(); 

private int getValue() { 
    try { 
    return Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
    return 42; 
    } 
} 

hay không đây là thực tế phụ thuộc vào trường hợp sử dụng chính xác.

Tất cả trong tất cả, miễn là x là một biến cục bộ có phạm vi thích hợp, cách tiếp cận chung thực tế nhất có thể là để nó không phải là final.

Nếu, mặt khác, x là một biến thành viên, lời khuyên của tôi sẽ được sử dụng một phi final tạm thời trong quá trình khởi:

public class C { 
    private final int x; 
    public C() { 
    int x_val; 
    try { 
     x_val = Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
     x_val = 42; 
    } 
    this.x = x_val; 
    } 
} 
+0

Đối với một phạm vi địa phương, tôi đồng ý với bạn, tuy nhiên điều này thường xảy ra nhất với các biến mẫu. – dtech

+0

Tôi đoán nó có thể phản ánh một lỗi không thể thực hiện tham chiếu tĩnh đến phương thức getValue(), vì vậy chúng tôi giả sử sử dụng hàm tĩnh, có thể sai private static int getValue() .. @ NPE – gks

+0

Nếu this.x là một kiểu đối tượng như Integer, sau đó bạn cần thêm một chút nữa (thật đáng buồn). Nếu bạn để x_val không khai báo, trình biên dịch sẽ phàn nàn rằng nó có thể chưa được khởi tạo. Nếu sự sụp đổ cho khối catch là null, bạn cần phải khởi tạo trước thành null và có thể gán giá trị null trong catch cho clearity (đó là sở thích của tôi) hoặc có một catch rỗng. –

2

Không nó không phải là nơi phù hợp, hãy tưởng tượng bạn có nhiều Sau đó 1 câu lệnh trong khối try và catch của bạn, câu đầu tiên nói: x = 42. Sau khi một số khác báo cáo khối thử không thành công, và nó đi đến khối catch, nơi mà bạn nói x = 30. Bây giờ bạn đã xác định x hai lần.

+9

Trình biên dịch đủ thông minh để biết câu lệnh nào ném ra ngoại lệ nào. Nó có thể không được có thể trong mọi trường hợp, nhưng cũng giống như trình biên dịch có thể cho bạn biết trong một số trường hợp về mã chết vv nó sẽ có thể tìm ra nếu cuối cùng sẽ làm việc. – Stefan

+0

Để hỗ trợ những gì @Stefan đã nói, Clang có thể tìm ra điều này khi biên dịch Swift. –

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