JavaRush /Blog Java /Random-VI /Các ngoại lệ trong Java
Roman
Mức độ

Các ngoại lệ trong Java

Xuất bản trong nhóm
Khi tôi xem chủ đề “Ngoại lệ”, nhiều câu hỏi nảy sinh khiến tôi phải tìm kiếm câu trả lời ở nhiều góc khác nhau trên Internet để hiểu chi tiết cách thức hoạt động của nó. Vì vậy, tôi đã biên soạn lời giải thích của riêng mình, có thể dễ hiểu hơn đối với những người mới bắt đầu mới gặp hiện tượng này. Các ngoại lệ trong Java - 1Trong máy tính, ngắt là tín hiệu đến bộ xử lý cho biết một sự kiện đang xảy ra đòi hỏi phải có phản hồi ngay lập tức. Tín hiệu ngắt yêu cầu bộ xử lý tạm dừng chương trình đang chạy để có thể tiếp tục chương trình đó sau đó một chút, tức là máy tính phải ghi nhớ tất cả thông tin liên quan đến việc thực hiện chương trình. Sự gián đoạn như vậy chỉ là tạm thời, nếu không muốn nói là gây tử vong. Những gián đoạn như vậy có thể do mã chương trình hoặc do một số chức năng phần cứng gây ra (ví dụ: chỉ cần nhấn các phím trên bàn phím; ví dụ: bộ hẹn giờ để tự động tắt máy tính). Số lượng Ngắt được giới hạn ở một số nhất định, được tích hợp trong quá trình sản xuất một bộ xử lý cụ thể, nghĩa là các "kênh" giao tiếp đặc biệt được phân bổ cho việc này, cho phép bạn truy cập vào bộ xử lý mà bỏ qua tất cả các quy trình khác. Các ngắt cũng được tạo tự động khi xảy ra lỗi trong mã chương trình đang thực thi (ví dụ: nếu xảy ra phép chia cho 0). Những gián đoạn như vậy theo truyền thống được gọi là bẫy hoặc ngoại lệ . Trong những trường hợp như vậy, người ta thường nói: “Ngoại lệ đã được ném”, tức là một Ngoại lệ đã được kích hoạt hoặc một Ngoại lệ đã được ném (ném), nghĩa là một yêu cầu Ngắtvới câu hỏi “phải làm gì?” gửi đến bộ xử lý. Tại thời điểm này, bộ xử lý ngừng hoạt động, ghi nhớ điểm mà nó dừng lại, hay đúng hơn là cụm của ô tiếp theo, thông tin từ đó phải được thực thi. Toàn bộ chuỗi lệnh đã thực hiện và KHÔNG thực hiện được ghi nhớ. Sau đó, bộ xử lý sẽ đọc hướng dẫn từ bộ nhớ để thực hiện hành động trong trường hợp xảy ra lỗi như vậy. Theo hướng dẫn này, nó có thể nhập các giá trị mới vào các cụm nhất định, thêm một số chuỗi hành động hoặc một chu trình mới (ví dụ: chu trình quay lại hoặc lặp lại), v.v., nghĩa là, tùy thuộc vào lỗi, được đặt trước đó hướng dẫn xuống được thực hiện. Bản thân hệ thống máy tính có nhiều Ngắt tự động được tích hợp sẵn, được kích hoạt sau một khoảng thời gian nhất định, chẳng hạn như để kiểm soát các quy trình đang chạy trên máy tính hoặc chạy các cảnh báo đã đặt, thu thập các tín hiệu bên ngoài đến và các bộ chuyển đổi dữ liệu khác nhau. Điều đáng ghi nhớ là một số lượng lớn các ngắt, vì một số lý do, hoàn toàn có thể “treo” hệ thống. Lỗi trong mã chương trình sẽ tự động gây ra sự gián đoạn trong bộ xử lý và nó sẽ cố gắng xử lý theo hướng dẫn đã đặt ra. Nhưng không phải tất cả các ngắt đều được thiết kế để xử lý chúng, hoặc nó có thể tạo ra một quy trình không phù hợp với chúng ta, chẳng hạn, nó sẽ làm hỏng ứng dụng. Do đó, trong lập trình, bạn có thể tổ chức ngắt của riêng mình cho một đoạn mã nhất định mà người lập trình có thể nhận thấy khả năng xảy ra lỗi. Trong trường hợp này, lỗi sẽ được xử lý trong chương trình và sẽ không liên hệ với bộ xử lý để được hướng dẫn xử lý. Định nghĩa của các khối như vậy được sắp xếp bằng cách tạo Đối tượng “Ngoại lệ” . Đối tượng này được tạo tự động trong khối try-catch. Khối >tryđược kiểm tra xem có lỗi hay không và nếu có lỗi, chương trình sẽ chuyển đến khối catch, nơi các hành động được thực hiện để ngăn chặn hoặc san bằng lỗi. Ví dụ: nếu chúng ta nhập Số từ bàn phím , sau đó phải cộng và trừ, thì việc nhập Chữ cái từ bàn phím sẽ khiến chúng ta không thể cộng chúng bằng Số (hãy biểu thị tổng của hai biến này bằng chữ S). Vì vậy, với tư cách là một đội, trychúng ta phải kiểm tra xem số A, chứa Số, có thể được thêm vào số B, chứa Chữ cái (tức là S = A + B) hay không, và nếu điều này là không thể và không thể thì chắc chắn phải thực hiện các biện pháp để KHÔNG xảy ra Lỗi và một Gián đoạn mới với câu hỏi “phải làm gì?” không bay tới bộ xử lý. Nếu không có Ngoại lệ trong chương trình, việc thực thi nó sẽ bị bộ xử lý làm gián đoạn. Nếu có Ngoại lệ, khi bị lệnh “bắt” try, điều khiển sẽ chuyển sang lệnh catch, lệnh này có thể đặt ra một giải pháp thay thế, ví dụ: chúng ta sẽ không cộng hai số này mà đặt S = A.
int a = 4;
String b = “hello”;
int S = 0;
 try {
   S = a + b;
   int r = 1;
 } catch (Exception igogo1) {
   S = a;
 }
 return S;
/* chuỗi “int r = 1;” không được thực thi vì đã xảy ra lỗi và chương trình chuyển hướng hoạt động trực tiếp đến trình xử lý ngoại lệ (khối bắt*/ Do đó, sự hiện diện của Ngoại lệ là cơ hội để giải quyết vấn đề trong chương trình mà không cần ném nó vào cấp độ bộ xử lý. Đối tượng “Ngoại lệ”, được tạo tự động trong khối trykhi phát hiện thấy lỗi, chứa giá trị của loại lỗi. Hãy gọi nó là “OurException” - đối với trường hợp cụ thể của chúng tôi kèm theo mô tả về lỗi cụ thể của chúng tôi. Những người tạo ra ngôn ngữ Java đã tạo trước một danh sách nhất định các lỗi điển hình và các tùy chọn điển hình để sửa chúng, nghĩa là trong java có một thư viện Ngoại lệ nhất định mà chúng ta có thể sử dụng để xử lý một lỗi đã xảy ra, vì vậy như không tự viết mã xử lý và do đó OurException rất có thể đã có ai đó được mô tả, vì vậy chúng tôi chỉ cần biết tên của ngoại lệ nào trong số này để chèn vào chương trình của mình nhằm xử lý mã có khả năng xảy ra lỗi. Nếu chúng ta mắc lỗi và chọn một Exception không chính xác từ thư viện thì bộ xử lý sẽ không “bắt” được nó, lỗi sẽ không tìm ra giải pháp trong chương trình và yêu cầu sẽ được gửi đến bộ xử lý. Nhưng có một cách dành cho người lười biếng. Nếu chúng ta không biết tên của ngoại lệ mà chúng ta cần từ thư viện, thì chúng ta có thể lấy tên chung có tên “ Exception ”, như trong ví dụ được mô tả ở trên. Ngoại lệ này có khả năng xử lý bất kỳ loại lỗi nào, nhưng nó không có khả năng cung cấp thông tin cụ thể về sự cố mà chúng tôi có thể ghi lại. Thư viện các Ngoại lệ được viết trước đó bao gồm các Ngoại lệ được kiểm tra và không được kiểm tra . Những cái có thể kiểm tra là những cái có thể sửa được mà không làm gián đoạn công việc của chương trình, nghĩa là nếu chúng ta cố mở một tệp trong một thư mục không tồn tại, hệ thống sẽ cho chúng ta biết về nó, chúng ta có thể thả tệp đó vào thư mục mong muốn và tiếp tục chương trình. Trên thực tế, đó là một yêu cầu về Ngắt đã được gửi đến bộ xử lý , nhưng không có câu hỏi: "hãy tìm xem phải làm gì với vấn đề này?!?!" Chúng tôi đã gửi một Ngắt mà chính chúng tôi đã phát hiện ra, với một lệnh làm sẵn mà bộ xử lý đã xử lý và tiếp tục thực hiện chương trình. Bỏ chọn là những lỗi không thể sửa được và chương trình sẽ bị đóng trước khi hoàn thành, tức là một yêu cầu Ngắt sẽ được gửi đến bộ xử lý., trong mọi trường hợp sẽ làm gián đoạn việc thực hiện chương trình. Điểm duy nhất khi viết những trường hợp ngoại lệ như vậy trong chương trình là để cho người dùng hiểu điều gì đã xảy ra, vì khi gặp phải sự gián đoạn này, chúng tôi có thể hiển thị một thông báo thông tin trên màn hình do chương trình đã bị lỗi. Lý do thứ hai để phát hiện những gián đoạn như vậy là khả năng ghi lại chúng vào nhật ký để phân tích tiếp theo (bạn đã bị hack, nhưng ít nhất bạn biết ở đâu). Hậu quả của sự hiện diện của các thư viện như vậy là cần phải nhớ đưa chúng vào. (Ví dụ: có thể tìm thấy danh sách các Ngoại lệ được kiểm tra và không được kiểm tra với các thư viện tại đây ) Nếu chúng tôi không biết chính xác nên đưa vào thư viện nào hoặc có một số tùy chọn lỗi thì chúng tôi có thể catchliệt kê một số Ngoại lệ bắt buộc. Bản thân hệ thống sẽ chọn trình xử lý chính xác nếu nó có trong danh sách. Thay vì một Ngoại lệ cụ thể, bạn có thể viết một “ Ngoại lệ ” chung chung có thể xử lý bất kỳ loại Ngoại lệ nào nếu nó không được xử lý trong các khối trước đó.
int a = 4;
String b = “hello”;
int S = 0;
 try {
   S = a + b;
   int r = 1;
 }
catch(NullPointerException blabla2) {
   System.out.println("Exception handling code for the NullPointerException.");
 }
catch (ArithmeticException ex1) {
   S = a;
 }
catch(Exception uups1) {
   System.out.println("Exception occured");
 }
 return S;
Nếu có một khối, tryNgoại lệ sẽ được tạo tự động. Nếu chúng ta cần áp dụng Ngoại lệ tại một thời điểm nào đó thì lệnh này sẽ được sử dụng throw. Nghĩa là, chúng tôi độc lập tạo một đối tượng new throw... sau đó, chương trình dừng hoạt động, gửi yêu cầu Ngắt đến bộ xử lý và được chuyển đến phần chương trình catch, từ đó nó cố gắng nhận hướng dẫn cho các hành động tiếp theo. Bằng cách tạo thủ công một Ngoại lệ , chúng ta có thể chỉ định loại cụ thể của nó từ thư viện:

throw new ArithmeticException("Access denied - You must be at least 18 years old.");
thì trình xử lý sẽ tìm kiếm một khối có Ngoại lệcatch cụ thể này - tìm kiếm trong toàn bộ chương trình, trên tất cả các phía . Sau lệnh xử lý ngoại lệ, tất cả mã chương trình còn lại sẽ KHÔNG được thực thi, ngoại trừ mã nằm trong khối . Nếu không tìm thấy trình xử lý trong chương trình, bộ xử lý sẽ được hỏi câu hỏi: “tự quyết định phải làm gì” và nó sẽ làm gián đoạn chương trình. Cuộc gọi ... có thể được thực hiện cả bên trong và bên ngoài khối (bất cứ nơi nào trong chương trình) catchthrowcatchnew throw>try
try {
   /* функция or действие, в котором есть сомнения. То есть: «попробуй выполнить это, а если не получится, а, если не получится, запускай режим исключения» */
   throw new CallForException(); /* Назначаем исключение, которое будет работать в случае наличия ошибки в функции, описанной выше. Здесь исключение «CallForException» - берется из библиотеки существующих исключений */
} catch (CallForException ee1) {
   /* Корректируем ошибку, чтобы программа не «отвалилась» or выводим сообщение об ошибке or что-то ещё */
} finally {
   /* этот блок работает всегда независимо от того была ошибка or нет. А если была, то сработало ли решение в catch or нет */
   /* часто используется для подчистки хвостов, например, для закрытия запущенного file or базы данных */
   /* в ряде случаев блок catch вообще может быть опущен и оставлен только блок finally и наоборот finally может быть опущен и оставлен только catch */
   /* Не допускается использование этого блока в ряде случаев, например, когда функция System.exit() запущена or другие системные Исключения, типа «отключение электроэнергии» и т.п. */
}

Thông báo ngoại lệ

Các phương thức do ai đó viết trước đây có thể bao gồm việc đưa ra Ngoại lệ. Để đảm bảo an toàn, lập trình viên viết mã đã cảnh báo những lập trình viên tiếp theo rằng có thể xảy ra lỗi trong phương pháp anh ta viết. Vì vậy, ví dụ, phương pháp tạo tệp được mô tả bên dưới quy định rằng khi tạo tệp có thể xảy ra lỗi (không có tệp nào ở đường dẫn đã cho), điều đó có nghĩa là sẽ cần một trình xử lý lỗi:
public void createFile(String path, String text) throws IOException {
    FileWriter writer = new FileWriter(path, true);
    writer.write(text);
    writer.close();
}
Nhưng đồng thời, bản thân nó không có trình xử lý, điều đó có nghĩa là bây giờ chúng ta sẽ không thể gọi phương thức đã viết trong chương trình của mình ở chế độ bình thường. Bây giờ chúng ta phải viết một trình xử lý lỗi và gọi phương thức này trong khối try:
String filePath = "hello.txt";
String text = "Hello World";

try {
    createFile(filePath, text);
} catch (IOException ex) {
    System.err.println("Error creating file: " + ex);
}

Ngoại lệ gốc

Có thể viết các ngoại lệ của riêng bạn để xử lý một số lỗi nhất định nếu các thư viện hiện có không đủ cho chúng tôi. Để làm điều này, chúng ta chỉ cần tạo một lớp kế thừa từ lớp Exception
public class StudentNotFoundException extends Exception {

    public StudentNotFoundException (String message) {
        super(message);
    }
}
Có hai quy tắc cần ghi nhớ khi tạo ngoại lệ của riêng bạn:
  1. Tên lớp của chúng tôi phải kết thúc bằng "Ngoại lệ"
  2. Lớp này phải chứa một hàm tạo với một biến chuỗi mô tả chi tiết về vấn đề Ngoại lệ. Trong hàm tạo, siêu hàm tạo được gọi và một thông báo được truyền đi.
Một ví dụ về việc sử dụng ngoại lệ được tạo:
public class StudentManager {
    public Student find(String studentID) throws StudentNotFoundException {
        if (studentID.equals("123456")) {
            return new Student();
        } else {
            throw new StudentNotFoundException(
                "Could not find student with ID " + studentID);
        }
    }
}
Chúng tôi bắt Ngoại lệ này bằng mã:
public class StudentTest {
    public static void main(String[] args) {
        StudentManager manager = new StudentManager();
         try {
            Student student = manager.find("0000001");
        } catch (StudentNotFoundException ex) {
            System.err.print(ex);
        }
    }
}
Kết quả thực hiện chương trình sẽ là: Sinh viênNotFoundException: Không thể tìm thấy sinh viên có ID 0000001

Tại sao bạn cần viết Ngoại lệ?

Năm 1996, tên lửa Ariane 5 bị rơi do chuyển đổi sai biến float thành biến số nguyên. Không có trường hợp ngoại lệ hoặc cách xử lý nào cho tình huống này. Nếu trong khi tải xuống tệp mà bị mất kết nối với Internet thì sự hiện diện của Ngoại lệ sẽ cho phép bạn tiếp tục tải xuống sau khi kết nối được khôi phục. Nếu không có Ngoại lệ, quá trình tải xuống sẽ phải bắt đầu lại.

Người giới thiệu:

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION