2011-02-03 47 views
19

Tôi chưa bao giờ sử dụng mệnh đề "ném", và hôm nay một người bạn đời nói với tôi rằng tôi phải ghi rõ trong khai báo phương thức ngoại lệ mà phương pháp có thể ném. Tuy nhiên, tôi đã sử dụng ngoại lệ mà không gặp phải vấn đề gì mà không cần làm, vì vậy, tại sao nó lại cần thiết nếu, trên thực tế, nó là cần thiết?Điều gì sẽ xảy ra nếu một phương thức ném ngoại lệ không được chỉ định trong khai báo phương thức bằng "ném"

+0

Bạn chỉ bị buộc phải chỉ định ngoại lệ được kiểm tra (và điều đó thực sự gây phiền nhiễu). Khi bạn không làm như vậy trình biên dịch nên khiếu nại. –

+0

Tôi đã bỏ phiếu để mở câu hỏi này vì câu hỏi và câu trả lời đưa ra mức độ phù hợp tốt về ** ném ** với ** ngoại lệ ** và ** không được kiểm tra **. – AdrianHHH

Trả lời

23

Java có hai loại ngoại lệ khác nhau: kiểm tra Ngoại lệ và bỏ chọn Ngoại lệ.

Trường hợp ngoại lệ không được chọn là các lớp con của RuntimeException và bạn không phải thêm tuyên bố ném. Tất cả các ngoại lệ khác phải được xử lý trong phần thân phương thức, hoặc với câu lệnh try/catch hoặc khai báo ném.

Ví dụ về ngoại lệ không được kiểm tra: IllegalArgumentException đôi khi được sử dụng để thông báo, rằng một phương pháp đã được gọi với các đối số bất hợp pháp. Không cần ném.

Ví dụ về ngoại lệ đã kiểm tra: IOException rằng một số phương pháp từ gói java.io có thể bị ném. Hoặc sử dụng try/catch hoặc thêm throws IOException vào khai báo phương thức và xử lý ngoại lệ ủy nhiệm cho người gọi phương thức.

+0

'ném' các từ khóa trợ giúp để ủy quyền xử lý ngoại lệ cho các thành phần khác. Xem bản trình diễn video: http://www.bitspedia.com/2013/11/how-to-delegate-exception-handling.html –

4
  1. Bạn cần khai báo ngoại lệ đã kiểm tra mà phương thức của bạn sẽ ném.
  2. Nếu bạn tuyên bố 'ném ngoại lệ' mà phần lớn bao gồm hầu hết nếu không phải tất cả ngoại lệ đã kiểm tra
  3. Bạn luôn có thể ném ngoại lệ thời gian chạy không được kiểm tra và không phải khai báo.

Im khá chắc chắn nếu bạn cố gắng ném ngoại lệ đã kiểm tra và chưa khai báo phương thức là ném loại đó, mã sẽ không biên dịch (kiểm tra ngay bây giờ).

EDIT, phải vì thế nếu bạn thử một cái gì đó đơn giản như

public static void main(String[] args) { 
    throw new Exception("bad"); 
} 

bạn nhận được một lỗi biên dịch.

Cụ thể cho câu hỏi của bạn, nếu bạn gọi phương thức được khai báo để ném ngoại lệ, bạn phải thử/nắm bắt lời gọi phương thức hoặc tuyên bố rằng phương thức của bạn sẽ ném ngoại lệ.

+0

Vấn đề là tôi không biết rằng có những ngoại lệ được kiểm tra và không được kiểm tra. Tôi sẽ chấp nhận câu trả lời của bạn nếu không phải vì Andreas_D đã cho tôi câu trả lời hoàn hảo. Cảm ơn! – bluehallu

13

Nếu một phương thức được khai báo với từ khóa ném thì bất kỳ phương thức nào khác muốn gọi phương thức đó phải được chuẩn bị để bắt hoặc khai báo rằng chính nó sẽ ném một ngoại lệ.

Ví dụ nếu bạn muốn tạm dừng các ứng dụng mà bạn phải gọi Thread.sleep(milliseconds);

Nhưng tờ khai cho phương pháp này nói rằng nó sẽ ném ra một Tuyên bố InterruptedException

:

public static void sleep(long millis) throws InterruptedException 

Vì vậy, nếu bạn muốn gọi nó là ví dụ trong phương pháp chính của bạn, bạn phải nắm bắt nó:

public static void main(String args[]) { 
    try { 
     Thread.sleep(1000); 
    } catch(InterruptedException ie) { 
     System.out.println("Opps!"); 
    } 
} 

Hoặc thực hiện phương pháp này cũng tuyên bố rằng nó được ném một ngoại lệ:

public static void main(String args[]) throws InterruptedException { 
    Thread.sleep(1000); 
} 
+0

trong ví dụ cuối cùng của bạn, làm cách nào để tôi nắm bắt ngoại lệ? –

+0

@somefolk Trong ví dụ cuối của tôi, chương trình sẽ không bắt được 'InterruptedException' vì' throws' nằm trong hàm 'main()'. Nếu xảy ra thì chương trình sẽ đột ngột kết thúc. – Anton

6

Nó có thể xảy ra, ngay cả với kiểm tra trường hợp ngoại lệ. Và đôi khi nó có thể phá vỡ đăng nhập.

Giả sử một phương pháp thư viện sử dụng thủ thuật này để cho phép một thực hiện Runnable có thể ném IOException:

class SneakyThrowTask implements Runnable { 

    public void run() { 
     throwSneakily(new IOException()); 
    } 

    private static RuntimeException throwSneakily(Throwable ex) { 
     return unsafeCastAndRethrow(ex); 
    } 

    @SuppressWarnings("unchecked") 
    private static <X extends Throwable>X unsafeCastAndRethrow(Throwable ex) throws X { 
     throw (X) ex; 
    } 

} 

Và bạn gọi nó như thế này:

public static void main(String[] args) { 
    try { 
     new SneakyThrowTask().run(); 
    } catch (RuntimeException ex) { 
     LOGGER.log(ex); 
    } 
} 

Trường hợp ngoại lệ sẽ không bao giờ được đăng nhập. Và bởi vì đó là ngoại lệ được kiểm tra, bạn không thể viết điều này:

public static void main(String[] args) { 
    try { 
     new SneakyThrowTask().run(); 
    } catch (RuntimeException ex) { 
     LOGGER.log(ex); 
    } catch (IOException ex) { 
     LOGGER.log(ex); // Error: unreachable code 
    } 
} 
+0

Nhưng bạn có bao giờ viết mã như vậy không? Chỉ cần tự hỏi trong tình huống nào người ta có thể muốn viết mã như vậy – Sameer

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