Computer >> Máy Tính >  >> Lập trình >> Java

Các ngoại lệ trong Java và cách xử lý chúng

Là một nhà phát triển Java, bạn nên có kiến ​​thức tốt về các ngoại lệ và xử lý ngoại lệ của Java.

Hướng dẫn này cung cấp những kiến ​​thức cơ bản mà mọi lập trình viên phải có khi làm việc với các chương trình Java. Để bắt đầu, hãy bắt đầu với việc hiểu chính xác Java Exceptions là gì.

Trường hợp ngoại lệ của Java là gì

Một chương trình Java có thể gặp sự cố dẫn đến chương trình bị chấm dứt đột ngột trong quá trình thực thi. Những vấn đề này được gọi là ngoại lệ.

Một lập trình viên giỏi phải có khả năng nhận ra các lỗi có thể xảy ra trong quá trình thực thi và cung cấp các lộ trình thay thế để chương trình thực hiện trong trường hợp ngoại lệ đó. Thực hành này được gọi là xử lý ngoại lệ.

Bây giờ bạn có thể tự hỏi tại sao chúng ta cần xử lý ngoại lệ. Tại sao không viết các chương trình sẽ không có ngoại lệ?

Tại sao Chúng tôi Cần Xử lý Ngoại lệ

Hóa ra, việc viết các chương trình không có ngoại lệ không dễ dàng như người ta vẫn tưởng. Hầu hết thời gian, những lỗi không thể tránh khỏi này nằm ngoài tầm kiểm soát của lập trình viên.

Các chương trình chấp nhận đầu vào của người dùng dễ rơi vào trường hợp ngoại lệ vì đầu vào không hợp lệ mà người dùng cung cấp. Việc đọc các tệp bên ngoài cũng vậy khi xem xét khả năng chúng đã bị di chuyển, đổi tên hoặc xóa bởi một nguồn bên ngoài mà lập trình viên không biết.

Trong những trường hợp như vậy, chương trình phải có khả năng xử lý ngoại lệ một cách duyên dáng mà không phải chấm dứt việc thực thi.

Hệ thống phân cấp của Java Exceptions

Tất cả các ngoại lệ trong Java phải là con của Exception lớp, chính nó là con của Throwable lớp học.

Hai lớp con chính của Exception lớp là RuntimeExceptionIOException .

Ngoại lệ so với Lỗi

Một lớp con khác của Throwable lớp là Error lớp. Tuy nhiên, các lỗi khác với các trường hợp ngoại lệ.

Lỗi chỉ ra các vấn đề mà JVM có thể gặp phải trong quá trình thực thi. Những vấn đề này thường nghiêm trọng và không thể khắc phục được. Rò rỉ bộ nhớ và các vấn đề không tương thích với thư viện là những lý do phổ biến gây ra lỗi trong chương trình.

StackOverflowErrorOutOfMemoryError là hai ví dụ về Lỗi Java.

Ngoại lệ được Kiểm tra và Bỏ chọn

Chúng ta có thể chia Ngoại lệ Java thành hai loại chính: đã kiểm tra bỏ chọn ngoại lệ.

Các ngoại lệ được kiểm tra là các ngoại lệ cần được xử lý trong chương trình trước khi biên dịch. Nếu những ngoại lệ này không được xử lý, chương trình sẽ không được trình biên dịch Java biên dịch. Do đó, chúng còn được gọi là các ngoại lệ thời gian biên dịch. IOExceptions là những ví dụ điển hình về các trường hợp ngoại lệ đã được kiểm tra.

Các ngoại lệ không được kiểm tra là các ngoại lệ mà trình biên dịch bỏ qua khi biên dịch chương trình. Việc chúng tôi có xử lý các ngoại lệ này trong chương trình hay không không quan trọng khi chương trình được biên dịch. Vì xử lý ngoại lệ không được áp dụng cho các ngoại lệ này, chương trình của chúng tôi có thể chạy vào RuntimeExceptions dẫn đến việc chấm dứt chương trình.

Tất cả các lớp mở rộng RuntimeException lớp là những ngoại lệ không được kiểm tra. Hai ví dụ về các lớp như vậy là NullPointerExceptionArrayIndexOutOfBoundsException .

Các phương thức thường được sử dụng trong lớp ngoại lệ

Chúng ta sẽ xem xét một số phương pháp thường được sử dụng trong Java Exception lớp:

  1. getMessage :trả về một thông báo chứa thông tin chi tiết về trường hợp ngoại lệ đã xảy ra.
  2. printStackTrace :trả về dấu vết ngăn xếp của ngoại lệ đã xảy ra.
  3. toString :trả về tên lớp và thông báo được trả về bằng getMessage phương pháp.

Cách Xử lý Ngoại lệ

Hãy xem cách chúng tôi có thể xử lý các ngoại lệ trong Java:

thử bắt

Chúng tôi có thể nắm bắt các trường hợp ngoại lệ và xử lý chúng đúng cách bằng cách sử dụng try-catch khối trong Java.

Trong cú pháp này, phần mã dễ bị ném ngoại lệ được đặt bên trong khối try và khối / khối bắt bắt ngoại lệ / ngoại lệ đã ném và xử lý chúng theo logic mà chúng tôi cung cấp.

Cú pháp cơ bản của khối try-catch như sau:

try {
    //exception-prone code
}
catch(Exception e) {
    //error handling logic
}

Với cách tiếp cận này, chương trình không tạm dừng thực thi khi chương trình đưa ra một ngoại lệ, thay vào đó, nó được xử lý một cách duyên dáng.

Chúng ta sẽ xem cách xử lý IOExceptions được ném bởi FileReader trong một chương trình Java.

Ví dụ:

import java.io.FileReader;

public class TryCatchBlockExample {

    public static void main(String[] args) {

        try {
            FileReader file = new FileReader("source.txt");
            file.read();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Ở đây, chúng tôi đã sử dụng một khối bắt duy nhất để xử lý FileNotFoundException ném khi khởi tạo FileReader lớp và IOException được ném bởi read() phương thức của FileReader lớp học.

Cả hai ngoại lệ này đều là con của Exception lớp học.

Chúng ta cũng có thể sử dụng nhiều câu lệnh catch để bắt các loại lỗi khác nhau do mã bên trong câu lệnh try đơn. Đối với ví dụ trước, chúng ta có thể sử dụng một khối bắt để bắt FileNotFoundException và một khối bắt khác cho IOException như đoạn mã sau hiển thị:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchBlockExample {

    public static void main(String[] args) {

        try {
            FileReader file = new FileReader("source.txt");
            file.read();
            file.close();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
}

Nếu ngoại lệ được ném khớp với ngoại lệ được xử lý bởi câu lệnh catch đầu tiên, thì nó sẽ được xử lý bởi logic bên trong câu lệnh catch đầu tiên.

Nếu các ngoại lệ không khớp, nó được chuyển đến câu lệnh bắt thứ hai. Nếu có nhiều hơn hai câu lệnh catch, quá trình này sẽ tiếp tục cho đến khi ngoại lệ đạt đến một câu lệnh catch bắt được loại của nó.

Kể từ FileNotFoundException là một kiểu con của IOException , sử dụng câu lệnh catch thứ 2 để bắt một FileNotFoundException sẽ không hoạt động. Nó sẽ được xử lý bởi câu lệnh bắt đầu tiên và không bao giờ đến câu lệnh thứ hai.

Lưu ý:Bắt buộc phải sử dụng ít nhất một câu lệnh bắt với câu lệnh try.

cuối cùng

Khi chúng tôi sử dụng try-catch khối để bắt các ngoại lệ trong chương trình của chúng tôi, có những trường hợp chúng tôi muốn triển khai một số logic bất chấp thực tế là liệu một ngoại lệ có được bắt hay không. Trong những trường hợp như vậy, chúng tôi có thể sử dụng try-catch-last thay vì chỉ thử bắt khối.

Sau đó, mã bên trong finally câu lệnh được thực hiện cho dù có ngoại lệ xảy ra hay không. finally câu lệnh phải luôn ở cuối khối try-catch-last.

Ví dụ:khi chúng tôi sử dụng FileReader để đọc một tệp, điều cần thiết là phải đóng tệp đã mở khi kết thúc quá trình xử lý cho dù có ngoại lệ xảy ra hay không. Để đảm bảo điều này, chúng tôi có thể đặt mã để đóng tệp bên trong finally tuyên bố.

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchFinallyBlockExample {

    public static void main(String[] args) {
        FileReader file = null;
        try {
            file = new FileReader("source.txt");
            file.read();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        finally {
            file.close();
        }
    }
}

Tuy nhiên, nếu bạn cố gắng biên dịch mã trên, mã sẽ không được biên dịch do IOException không được xử lý . Điều này là do close() phương thức của FileReader lớp cũng có thể ném IOExceptions . Vì vậy, chúng ta phải đặt phần này bên trong một khối thử khác như thế này:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchFinallyBlockExample {

    public static void main(String[] args) {
        FileReader file = null;

        try {
            file = new FileReader("source.txt");
            file.read();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                file.close();
            }
            catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ném

Xử lý lỗi bằng cách sử dụng throws từ khóa trong Java rất đơn giản. Trên thực tế, trong cách tiếp cận này, bạn không thực sự xử lý ngoại lệ tại nơi nó xảy ra. Thay vào đó, chúng ta ném ngoại lệ ra khỏi phương thức hiện tại cho phương thức được gọi là phương thức hiện tại. Sau đó, việc xử lý lỗi trở thành trách nhiệm của phương pháp bên ngoài.

Để loại bỏ một ngoại lệ ra khỏi một phương thức, bạn chỉ cần khai báo rằng phương thức này có thể ném ngoại lệ được xem xét. Hãy xem cách chúng tôi có thể xử lý IOExceptions được ném bởi FileReader sử dụng cách tiếp cận này.

Ví dụ:

import java.io.FileReader;
import java.io.IOException;

public class ThrowsExample {

    public void readFile throws IOException {
        FileReader file = new FileReader("source.txt");
        file.read();
        file.close();
    }
}

ném

Không giống như các cách tiếp cận khác trong danh sách này, throws từ khóa không được sử dụng để xử lý lỗi. Nhưng vì hầu hết mọi người nhầm lẫn giữa throws từ khóa có throws từ khóa, chúng tôi nghĩ tốt nhất nên thảo luận ở đây.

throws từ khóa được sử dụng để gọi một cách rõ ràng một ngoại lệ. Chúng ta có thể đưa ra một ngoại lệ mới được khởi tạo hoặc một ngoại lệ đã bị bắt bên trong phương thức.

public class ThrowExample {

    public void invalidate(int amount) throws Exception {
        if (amount < 500) {
            throw new Exception("Amount not sufficient");
        }
    }
}

Ngoại lệ do người dùng xác định

Ngoài việc sử dụng các ngoại lệ Java cài sẵn, bạn có thể xác định các ngoại lệ của riêng mình. Bạn có thể xác định chúng là ngoại lệ được chọn hoặc không được chọn. Để tạo một ngoại lệ đã kiểm tra mới, ngoại lệ mới của bạn phải mở rộng Exception lớp học.

Để tạo không được chọn ngoại lệ, mở rộng RuntimeException lớp học.

Trong ví dụ mã sau, chúng tôi đã tạo một ngoại lệ đã kiểm tra do người dùng xác định:

public class InvalidLengthException extends Exception {
    private int length;
    private String message;

    public InvalidLengthException(int length, String message) {
        this.length=length;
        this.message=message;
    }

    public int getAmount() {
        return this.length;
    }

    public String getMessage() {
        return this.message;
    }
}

Bây giờ chúng ta có thể sử dụng ngoại lệ trên bên trong logic chương trình của chúng ta như sau:

public class InputChecker {

    private int minLength;
    private int maxLength;

    public InputChecker(int minLength, int maxLength) {
        this.minLength=minLength;
        this.maxLength=maxLength;
    }

    public void checkStringLength(String strInput) throws InvalidLengthException {
        int strLength = strInput.length();
        if (strLength < minLength) {
            throw new InvalidLengthException(strLength, "Input should have minimum "+minLength+" characters");
        }
        else if (strLength > maxLength){
            throw new InvalidLengthException(strLength, "Input should have maximum "+maxLength+" character");
        }
    }
}

Nếu chúng tôi kiểm tra độ dài của một chuỗi bằng InputChecker , nó sẽ ném ra một InvalidLengthException nếu độ dài chuỗi dưới độ dài tối thiểu hoặc trên độ dài tối đa.

public class Main {

    public static void main(String[] args) {
        InputChecker ic = new InputChecker(2, 7);
        try {
            ic.checkStringLength("longer than the maximum length");
        }
        catch(InvalidLengthException e) {
            e.printStackTrace();
        }
    }
}

Khi chúng tôi chạy đoạn mã trên, nó sẽ ném ra một InvalidLengthException và chúng tôi sẽ nhận được kết quả sau:

InvalidLengthException: Input should have maximum 7 character
    at InputChecker.checkStringLength(InputChecker.java:17)
    at Main.main(Main.java:6)

Kết luận

Trong hướng dẫn này, chúng tôi đã giới thiệu nhanh và ngắn gọn cho bạn về Java Exceptions. Chúng tôi hy vọng rằng bây giờ bạn đã hiểu rõ về những ngoại lệ là gì và cách xử lý chúng trong chương trình Java của bạn.