Khi nào sử dụng ném trong khai báo phương thức Java?


82

Vì vậy, tôi nghĩ rằng tôi đã có hiểu biết cơ bản tốt về xử lý ngoại lệ trong Java, nhưng gần đây tôi đang đọc một số mã khiến tôi bối rối và nghi ngờ. Nghi ngờ chính của tôi mà tôi muốn giải quyết ở đây là khi nào một người nên sử dụng ném trong khai báo phương thức Java như sau:

    public void method() throws SomeException
    {
         // method body here
    }

Từ việc đọc một số bài viết tương tự, tôi thu thập được rằng ném được sử dụng như một loại khai báo rằng SomeException có thể được ném trong quá trình thực thi phương thức.

Sự nhầm lẫn của tôi đến từ một số mã trông như thế này:

     public void method() throws IOException
     {
          try
          {
               BufferedReader br = new BufferedReader(new FileReader("file.txt"));
          }
          catch(IOException e)
          {
               System.out.println(e.getMessage());
          }
     }

Có lý do gì mà bạn muốn sử dụng ném trong ví dụ này không? Có vẻ như nếu bạn chỉ đang thực hiện xử lý ngoại lệ cơ bản của một cái gì đó như IOException thì bạn chỉ cần khối try / catch và thế là xong.

Câu trả lời:


79

Nếu bạn đang bắt một loại ngoại lệ, bạn không cần phải ném nó đi, trừ khi bạn định ném lại nó. Trong ví dụ bạn đăng, nhà phát triển lẽ ra phải làm một việc này hoặc cách khác, không phải cả hai.

Thông thường, nếu bạn không định làm bất cứ điều gì ngoại trừ, bạn không nên bắt nó.

Điều nguy hiểm nhất bạn có thể làm là bắt một ngoại lệ và không làm bất cứ điều gì với nó.

Một cuộc thảo luận tốt về thời điểm thích hợp để ném các ngoại lệ là ở đây

Khi nào thì ném một ngoại lệ?


2
Có nên khai báo các ngoại lệ không được kiểm tra trong chữ ký phương thức bằng 'ném' hay không, hay chỉ sử dụng 'ném' cho các ngoại lệ đã kiểm tra?
Cody

Câu trả lời này không trực tiếp đề cập đến khía cạnh trung tâm của câu hỏi: Việc sử dụng throwstừ khóa.
Brent Bradburn

@hvgotcodes Điều gì xảy ra nếu tôi bắt gặp một ngoại lệ và không làm gì cả?
Manoj

@manoj bạn có nguy cơ bị hỏng mọi thứ và không thể tìm ra nó vì thông tin quan trọng bị mất. Đôi khi (không nhất thiết là java), bạn có thể bắt một ngoại lệ và không làm gì cả, nhưng những điều đó nên được ghi lại. Ví dụ: trong javascript, bạn có thể thử gọi chức năng có thể không tồn tại tùy thuộc vào trình duyệt. Đó không hẳn là một lỗi cần chú ý.
hvgotcodes

22

Bạn chỉ cần đưa mệnh đề ném vào một phương thức nếu phương thức ném một ngoại lệ đã được kiểm tra. Nếu phương thức ném một ngoại lệ thời gian chạy thì không cần phải làm như vậy.

Xem tại đây để biết một số thông tin cơ bản về các trường hợp ngoại lệ được kiểm tra và không được kiểm tra: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Nếu phương thức bắt được ngoại lệ và xử lý nó bên trong (như trong ví dụ thứ hai của bạn) thì không cần bao gồm mệnh đề ném.


9

Mã mà bạn đã xem không phải là lý tưởng. Bạn nên:

  1. Nắm bắt ngoại lệ và xử lý nó; trong trường hợp đó throwslà không cần thiết.

  2. Loại bỏ try/catch; trong trường hợp đó Exception sẽ được xử lý bởi một phương thức gọi.

  3. Nắm bắt ngoại lệ, có thể thực hiện một số hành động và sau đó ném lại ngoại lệ (không chỉ thông báo)


2

Bạn đúng, trong ví dụ đó, điều đó throwslà thừa. Có thể nó đã bị bỏ lại ở đó từ một số lần triển khai trước đó - có lẽ ngoại lệ ban đầu được ném ra thay vì bị bắt trong khối bắt.


2

Mã bạn đã đăng sai, nó sẽ ném một Ngoại lệ nếu đang bắt một ngoại lệ cụ thể để xử lý IOException nhưng ném ra các ngoại lệ không được bắt.

Cái gì đó như:

public void method() throws Exception{
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println(e.getMessage());
   }
}

hoặc là

public void method(){
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println("Catching IOException");
           System.out.println(e.getMessage());
   }catch(Exception e){
           System.out.println("Catching any other Exceptions like NullPontException, FileNotFoundExceptioon, etc.");
           System.out.println(e.getMessage());
   }

}


1

Trong ví dụ bạn đưa ra, phương thức sẽ không bao giờ ném IOException, do đó khai báo sai (nhưng hợp lệ). Tôi đoán rằng phương thức ban đầu đã ném IOException, nhưng sau đó nó đã được cập nhật để xử lý ngoại lệ bên trong nhưng khai báo không bị thay đổi.


1

Đây không phải là một câu trả lời, mà là một bình luận, nhưng tôi không thể viết bình luận với mã định dạng, vì vậy đây là bình luận.

Hãy nói rằng có

public static void main(String[] args) {
  try {
    // do nothing or throw a RuntimeException
    throw new RuntimeException("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Đầu ra là

test
Exception in thread "main" java.lang.RuntimeException: test
    at MyClass.main(MyClass.java:10)

Phương thức đó không khai báo bất kỳ Ngoại lệ "ném" nào, nhưng ném chúng! Bí quyết là các ngoại lệ được ném ra là RuntimeExceptions (không được chọn) không cần khai báo trên phương thức. Nó hơi gây hiểu lầm cho người đọc về phương pháp này, vì tất cả những gì cô ấy thấy là "ném e;" tuyên bố nhưng không có tuyên bố về ngoại lệ ném

Bây giờ, nếu chúng ta có

public static void main(String[] args) throws Exception {
  try {
    throw new Exception("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

Chúng ta PHẢI khai báo các ngoại lệ "ném" trong phương thức nếu không chúng ta sẽ gặp lỗi trình biên dịch.


Trình biên dịch thực hiện một phân tích tĩnh phức tạp đáng ngạc nhiên để quyết định xem có throwscần thiết hay không .
Brent Bradburn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.