2011-01-17 28 views
8
static int retIntExc() throws Exception{ 
    int result = 1; 
    try { 
     result = 2; 
     throw new IOException("Exception rised."); 
    } catch (ArrayIndexOutOfBoundsException e) { 
     System.out.println(e.getMessage()); 
     result = 3; 
    } finally { 
     return result; 
    } 
} 

Một người bạn của tôi là nhà phát triển .NET và hiện đang di chuyển sang Java và anh ấy hỏi tôi câu hỏi sau về nguồn này. Về lý thuyết, điều này phải là throw IOException("Exception rised.") và toàn bộ phương pháp retIntExc() phải throws Exception. Nhưng không có gì xảy ra, phương thức trả về 2.Ngoại lệ bị nuốt bởi cuối cùng là

Tôi chưa thử nghiệm ví dụ của anh ấy, nhưng tôi nghĩ rằng đây không phải là hành vi mong đợi.

CHỈNH SỬA: Cảm ơn mọi câu trả lời. Một số bạn đã bỏ qua thực tế rằng phương pháp được gọi là retIntExc, có nghĩa rằng đây chỉ là một số ví dụ thử nghiệm/thử nghiệm, cho thấy vấn đề trong cơ chế ném/đánh bắt. Tôi không cần 'sửa chữa', tôi cần giải thích lý do tại sao điều này xảy ra.

+0

Tại sao bạn không khai báo nó 'ném IOException'? – BoltClock

+0

http://stackoverflow.com/questions/65035/in-java-does-return-trump-finally –

Trả lời

16

Đây là lý do tại sao bạn không thể trở về từ một khối finally trong C# :)

Nó hoàn toàn hành vi đặt ra trong Mặc dù vậy, Java Language Specification. Nó được chỉ định trong section 14.20.2.

Nếu khối cuối cùng hoàn thành đột ngột vì lý do S, thì câu lệnh thử hoàn thành đột ngột vì lý do S (và vứt bỏ giá trị V bị loại bỏ và quên).

Trả lại là một ví dụ về việc hoàn thành đột ngột; nếu khối finally ném một ngoại lệ, điều đó sẽ cũng hoàn toàn đột ngột, mất ngoại lệ ban đầu.

Các trích dẫn ở trên là từ bộ lồng nhau này các điểm nhấn, để lại các tùy chọn mà không được áp dụng ở đây:

  • Nếu thực hiện các khối try hoàn đột ngột vì một ném của một giá trị V, sau đó có một sự lựa chọn:
    • Nếu kiểu thời gian chạy của V không thể gán cho tham số của bất kỳ mệnh đề nào của câu lệnh thử, thì khối cuối cùng được thực thi. Sau đó, có một lựa chọn:
      • Nếu khối cuối cùng hoàn thành đột ngột vì lý do S, thì câu lệnh thử hoàn thành đột ngột vì lý do S (và vứt bỏ giá trị V bị loại bỏ và quên).
+2

Cảm ơn. Đây là những gì tôi cần - tham khảo JLS. – fiction

3

Nó sẽ trở lại 2

finally luôn thực hiện

+0

-1 ** cuối cùng không phải lúc nào cũng thực thi ** và nó không in bất cứ thứ gì. – Ishtar

+0

hãy thử điều này. System.out.println (retIntExc()); và hãy suy nghĩ kỹ trước khi bỏ phiếu bất cứ điều gì! –

+0

cuối cùng thực sự không phải lúc nào cũng thực thi. – Woot4Moo

2

Khối finally thực thi không có vấn đề gì ngoại lệ được ném. Nó không chỉ thực thi sau khi các ngoại lệ bị bắt bởi các khối catch mà bạn khai báo. Nó thực thi sau khi try chặn và ngoại lệ bị bắt nếu có bất kỳ nào. Nếu phương pháp của bạn ném một ngoại lệ, nó không thể trả lại bất cứ điều gì trừ khi bạn nuốt nó trong phương pháp của bạn và trả lại result. Nhưng bạn không thể có cả hai.

Ngoài ra, trừ khi phương thức của bạn có bất kỳ mã nào khác, ArrayIndexOutOfBoundsException cũng sẽ không bao giờ gặp phải.

0

Các IOException lớp không phải là một đứa trẻ của ArrayIndexOutOfBoundsException lớp nên phần bắt sẽ không bao giờ thực hiện.

Nếu bạn thay đổi để nó nó này sẽ trở lại 3.

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 
      throw new ArrayIndexOutOfBoundsException ("Exception rised."); 
     } catch (ArrayIndexOutOfBoundsException e) { 
      System.out.println(e.getMessage()); 
      result = 3; 
     } finally { 
      return result; 
     } 
    } 
2

Điều này là do bạn đưa ra một tuyên bố trở lại trước khi ngoại lệ được thông qua máng và do đó giá trị hợp lệ được trả về. Bạn không thể trả về một giá trị và ném một ngoại lệ.

Xóa khối cuối cùng xung quanh lợi tức sẽ cho hành vi bạn muốn.

0

Tôi không hiểu tại sao hành vi này sẽ không được mong đợi. Đến cuối của kết quả khối mã này bằng 2.

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 

Sau đó bạn ném một ngoại lệ, nhưng khối catch của bạn bắt ngoại lệ của một loại khác để không có gì được thực thi.

 throw new IOException("Exception rised."); 
    } catch (ArrayIndexOutOfBoundsException e) { 
      ... 
    } 

Các khối finally được đảm bảo được thực thi, vì vậy bước cuối cùng là quay trở lại 2.

trở lại thành công này overrules trừ bọt. Nếu bạn muốn ngoại lệ tiếp tục bong bóng thì bạn không được trả lại trong khối cuối cùng.

0

Bằng cách đặt return trong phương thức cuối cùng, bạn ghi đè lên ngoại lệ và kết quả được trả về thay thế. Mã của bạn phải giống như sau:

static int retIntExc() throws Exception{ 
     int result = 1; 
     try { 
      result = 2; 
      throw new IOException("Exception rised."); 
     } catch (ArrayIndexOutOfBoundsException e) { 
      System.out.println(e.getMessage()); 
      result = 3; 
     } finally { 
      // do something 
     } 
     // it gets here only when exception is not thrown 
     return result; 
    } 
Các vấn đề liên quan