Tại sao chúng ta cần ngoại lệ?
Chỉ huy
public static void main(String[] args) { int a = 10; int b = 0; int number = a / b; System.out.println("Chương trình tiếp tục chạy"); }
Khi chạy đoạn mã trên, lỗi sau sẽ được báo cáo, nghĩa là mẫu số là 0.
Ngoại lệ trong luồng "main" java.lang.ArithmeticException: / bằng số không
gỡ rối
Nếu một đoạn mã Java gặp lỗi không nghiêm trọng, nó sẽ dừng chạy. Điều này không đáp ứng được nhu cầu thực tế và không tốt. Lúc này, try-catch được thực hiện trên mã có thể gây ra ngoại lệ để đảm bảo rằng chương trình có thể tiếp tục chạy ngay cả khi gặp ngoại lệ. Các cải tiến về mã như sau: (Có thể vẫn còn hơi khó hiểu và có phần giới thiệu chi tiết về cách xử lý ngoại lệ bên dưới).
public static void main(String[] args) { int a = 10; int b = 0; try { int number = a / b; } catch (Exception exception) { //exception.printStackTrace(); System.out.println("Lý do xảy ra ngoại lệ --> "+exception.getMessage()); //Đầu ra thông tin ngoại lệ } System.out.println("Chương trình tiếp tục chạy"); }
Giới thiệu bất thường
ý tưởng
Ngoại lệ đề cập đến nhiều tình huống bất ngờ khác nhau, chẳng hạn như: không tìm thấy tệp, lỗi kết nối mạng, tham số không hợp lệ, v.v. Ngoại lệ là sự kiện xảy ra trong quá trình thực thi chương trình làm gián đoạn luồng lệnh thông thường. (Lỗi cú pháp và lỗi logic trong quá trình phát triển không phải là ngoại lệ).
Biểu đồ phân cấp lớp ngoại lệ Java
Phân loại
1. Lỗi: Lỗi là lỗi nghiêm trọng và chương trình sẽ bị sập. Loại lỗi này thường chỉ ra sự cố với JVM khi mã của bạn đang chạy. Thông thường sẽ có Virtual MachineError (lỗi vận hành máy ảo), NoClassDefFoundError (lỗi định nghĩa lớp), v.v. Ví dụ: OutOfMemoryError: lỗi không đủ bộ nhớ; StackOverflowError: lỗi tràn ngăn xếp. Khi lỗi như vậy xảy ra, JVM sẽ chấm dứt luồng. Những lỗi này là ngoại lệ chưa được kiểm tra, không phải lỗi mã hóa. Do đó, các ứng dụng không nên xử lý những lỗi như vậy khi chúng xảy ra. Theo quy ước của Java, chúng ta không nên triển khai bất kỳ lớp con Lỗi mới nào! .
2. Ngoại lệ: Các vấn đề chung khác do lỗi lập trình hoặc các yếu tố bên ngoài ngẫu nhiên có thể được xử lý bằng cách sử dụng mã mục tiêu. Ví dụ, truy cập con trỏ null, cố gắng đọc một tệp không tồn tại, mất kết nối mạng, v.v. Nó có thể được chia thành hai loại:
Ngoại lệ thời gian chạy
Ngoại lệ xảy ra khi chương trình đang chạy thường đề cập đến lỗi logic trong lập trình, đây là những ngoại lệ mà lập trình viên nên tránh. Lớp java.lang.RuntimeException và các lớp con của nó là các ngoại lệ thời gian chạy. Các ngoại lệ thời gian chạy không cần phải được xử lý vì các ngoại lệ như vậy rất phổ biến. Nếu tất cả chúng được xử lý, nó có thể ảnh hưởng đến khả năng đọc và hiệu quả chạy của chương trình.
Ngoại lệ thời gian biên dịch
Khi lập trình, trình biên dịch sẽ kiểm tra các ngoại lệ cần được trình biên dịch xử lý.
Ngoại lệ thời gian chạy phổ biến
1.NullPointerException Ngoại lệ con trỏ Null.
2.ArithmeticException Ngoại lệ về phép toán.
3.ArrayIndexOutOfBoundsException Ngoại lệ về chỉ số mảng vượt quá giới hạn.
4. Ngoại lệ chuyển đổi kiểu ClassCastException.
5.NumberFormatException Định dạng số không đúng.
Ví dụ.
1.NullPointerException Ngoại lệ con trỏ Null.
Ngoại lệ này được đưa ra khi một ứng dụng cố gắng sử dụng null khi cần một đối tượng. Xem ví dụ mã sau.
public static void main(String[] args) { String name = null; System.out.println(name.length()); }
Báo cáo ngoại lệ sau:
2.ArithmeticException Ngoại lệ về phép toán.
Ngoại lệ này được đưa ra khi điều kiện hoạt động bất thường xảy ra. Ví dụ, khi một số nguyên được "chia cho số không", một thể hiện của lớp này được ném ra. Ví dụ được giới thiệu ở trên là một trường hợp như vậy, vì vậy tôi sẽ không nhắc lại ở đây. 3.ArrayIndexOutOfBoundsException: Ngoại lệ chỉ số mảng vượt quá giới hạn.
Ngoại lệ được đưa ra khi mảng được truy cập bằng chỉ mục không hợp lệ. Nếu chỉ số âm hoặc lớn hơn hoặc bằng kích thước mảng thì chỉ số đó không hợp lệ.
public static void main(String[] args) { int[] arr = {1,2,3}; cho (int i = 0; i <= arr.length; i++) { System.out.println(arr[i]); } }
Báo cáo ngoại lệ sau:
4. Ngoại lệ chuyển đổi kiểu ClassCastException.
Được ném khi có nỗ lực ép kiểu một đối tượng sang một lớp con mà nó không phải là một thể hiện.
lớp công khai ClassCastException { public static void main(String[] args) { A b = new B(); B b2 = (B) b; C c2 = (C) b; // ClassCastException được ném ở đây } } lớp A{} lớp B mở rộng A{} lớp C mở rộng A{}
Báo cáo ngoại lệ sau:
5. NumberFormatException: Định dạng số không đúng.
Ngoại lệ này xuất hiện khi một ứng dụng cố gắng chuyển đổi một chuỗi thành kiểu số, nhưng chuỗi đó không thể được chuyển đổi sang định dạng thích hợp.
public static void main(String[] args) { String name = "Số lượng tham chiếu"; int num = Integer.parseInt(name); }
Báo cáo ngoại lệ sau:
Các ngoại lệ biên dịch phổ biến
1.SQLException //Khi vận hành cơ sở dữ liệu, có thể xảy ra ngoại lệ khi truy vấn bảng. 2.IOException //Khi vận hành tệp, có thể xảy ra ngoại lệ. 3.FileNotFoundException //Khi vận hành tệp không tồn tại, có thể xảy ra ngoại lệ. 4.ClassNotFoundException //Khi tải lớp không tồn tại, có thể xảy ra ngoại lệ. 5.EOFException //Khi vận hành tệp, có thể xảy ra ngoại lệ ở cuối tệp. 6.illegalArguementException //Ngoại lệ tham số.
Xử lý ngoại lệ
Đường
1.try-catch-finally Người lập trình nắm bắt các ngoại lệ xảy ra trong mã và tự xử lý chúng. 2.throws Ném các ngoại lệ xảy ra và chuyển chúng cho người gọi (phương thức) để xử lý. Trình xử lý cấp cao nhất là JVM.
thử-bắt-cuối-cùng
minh họa
Khối try được sử dụng để chứa mã có khả năng bị lỗi. Khối catch được sử dụng để xử lý các ngoại lệ xảy ra trong khối try. Bạn có thể có nhiều khối try...catch trong chương trình tùy theo nhu cầu. Finally là tùy chọn. Nội dung của khối mã này yêu cầu finally phải được thực thi bất kể có xảy ra ngoại lệ trong khối mã try hay không. Do đó, mã giải phóng tài nguyên thường được đặt trong finally.
ngữ pháp
thử { //Mã đáng ngờ //Tạo đối tượng ngoại lệ tương ứng và truyền nó vào khối catch} catch (Ngoại lệ ngoại lệ) { //Xử lý ngoại lệ} cuối cùng { //Mã nghiệp vụ được thực thi bất kể ngoại lệ có xảy ra hay không (tùy chọn) }
Ví dụ
public static void main(String[] args) { int a = 10; int b = 0; try { int number = a / b; } catch (Exception exception) { //exception.printStackTrace(); System.out.println("Lý do xảy ra ngoại lệ --> "+exception.getMessage()); //Đầu ra thông tin ngoại lệ } System.out.println("Chương trình tiếp tục chạy"); }
Các biện pháp phòng ngừa
1. Nếu xảy ra ngoại lệ, mã sau ngoại lệ sẽ không được thực thi và sẽ trực tiếp đưa vào khối catch.
2. Nếu không có ngoại lệ nào xảy ra, khối mã thử sẽ được thực thi tuần tự và không nhập lệnh catch.
3. Nếu bạn muốn thực thi một mã nào đó bất kể có xảy ra ngoại lệ hay không (chẳng hạn như đóng kết nối, giải phóng tài nguyên, v.v.), hãy sử dụng mã - finally{}.
4. Có thể có nhiều câu lệnh catch để nắm bắt các ngoại lệ khác nhau (cho các xử lý nghiệp vụ khác nhau), yêu cầu ngoại lệ của lớp cha phải ở cuối và ngoại lệ của lớp con phải ở đầu, ví dụ (Exception ở cuối và NullPointerException ở đầu). Nếu ngoại lệ xảy ra, chỉ có một catch được khớp, như được hiển thị trong phần trình bày trường hợp.
public class TryCatchDetail { public static void main(String[] args) { try { Person person = new Person(); System.out.println(person.getName());//Nếu tên ở đây trống, ngoại lệ con trỏ null sẽ xảy ra. int a = 10; int b = 0; int res = a / b; } catch (NullPointerException e) { System.out.println("Ngoại lệ con trỏ NULL="+e.getMessage()); }catch (ArithmeticException e){ System.out.println("ngoại lệ số học="+e.getMessage()); }catch (Ngoại lệ e){ System.out.println(e.getMessage()); } finally { } } } class Person{ private String name = "jack"; public String getName(){ return name; } }
5. Bạn có thể sử dụng try-finally cùng nhau. Cách sử dụng này tương đương với việc không bắt được ngoại lệ, do đó chương trình sẽ bị sập/thoát trực tiếp. Kịch bản ứng dụng là thực thi một đoạn mã. Bất kể có xảy ra ngoại lệ hay không, một logic nghiệp vụ nhất định phải được thực thi.
public static void main(String[] args) { try { int a = 10; int b = 0; int res = a / b; } finally { System.out.println("cuối cùng đã được thực thi....."); } System.out.println("Chương trình tiếp tục thực thi....."); }
bản tóm tắt
1. Nếu không có ngoại lệ nào xảy ra, tất cả các câu lệnh trong khối try được thực thi và các câu lệnh trong khối catch không được thực thi. Nếu có finally, các câu lệnh trong finally cần được thực thi ở cuối. 2. Nếu xảy ra ngoại lệ, sau khi ngoại lệ xảy ra trong khối try, các câu lệnh còn lại trong khối try sẽ không còn được thực thi nữa. Các câu lệnh trong khối catch sẽ được thực thi. Nếu có khối finally, các câu lệnh trong khối finally cũng sẽ cần được thực thi! .
ném
minh họa
1. Nếu một phương thức (khi các câu lệnh trong đó được thực thi) có thể tạo ra một số loại ngoại lệ, nhưng không chắc chắn cách xử lý ngoại lệ này, thì phương thức này phải tuyên bố rõ ràng rằng nó ném ra một ngoại lệ, cho biết rằng phương thức sẽ không xử lý các ngoại lệ này, mà người gọi phương thức có trách nhiệm xử lý chúng.
2. Trong khai báo phương thức, sử dụng câu lệnh throws để khai báo danh sách các ngoại lệ cần ném. Kiểu ngoại lệ sau throws có thể là kiểu ngoại lệ được tạo trong phương thức hoặc lớp cha của nó.
Ví dụ
public static void readFile(String file)throws FileNotFoundException { //Hoạt động đọc tệp có thể tạo ra ngoại lệ của FileNotFoundException loại FilelnputStream fis = new FilelnputStream("d://aa.txt"); }
Các biện pháp phòng ngừa
1. Các ngoại lệ biên dịch phải được xử lý trong chương trình, chẳng hạn như try-catch hoặc throws.
2. Đối với các ngoại lệ thời gian chạy, nếu chúng không được xử lý trong chương trình, theo mặc định, phương thức throws sẽ xử lý chúng.
3. Khi một lớp con ghi đè phương thức của lớp cha, quy định về việc ném ngoại lệ: Kiểu ngoại lệ do phương thức bị lớp con ghi đè ném ra phải giống với kiểu ngoại lệ do lớp cha ném ra hoặc là kiểu con của kiểu ngoại lệ do lớp cha ném ra.
4. Trong quá trình throws, nếu có phương thức try-catch thì tương đương với việc xử lý ngoại lệ và không cần throws.
Ngoại lệ tùy chỉnh
ý tưởng
Khi một số "lỗi" xảy ra trong chương trình, nhưng thông tin lỗi không được mô tả và xử lý trong lớp con Throwable, bạn có thể thiết kế lớp ngoại lệ của riêng mình để mô tả thông tin lỗi.
bước chân
1. Định nghĩa lớp: tên lớp ngoại lệ tùy chỉnh (do chính lập trình viên viết) kế thừa Exception hoặc RuntimeException 2. Nếu nó kế thừa Exception, thì đó là ngoại lệ biên dịch 3. Nếu nó kế thừa RuntimeException, thì đó là ngoại lệ đang chạy (nói chung, nó kế thừa RuntimeException).
Ví dụ
Yêu cầu: Khi chúng ta nhận được độ tuổi của một đối tượng Person, độ tuổi đó phải nằm trong khoảng từ 18 đến 120, nếu không, một ngoại lệ tùy chỉnh sẽ được đưa ra (yêu cầu phải kế thừa RuntimeException) và một thông báo nhắc sẽ được đưa ra.
public class CustomException { public static void main(String[] args) { int age = 180; //Yêu cầu phạm vi phải nằm trong khoảng từ 18 đến 120, nếu không, một ngoại lệ tùy chỉnh sẽ được ném if (!(age >= 18 && age <= 120)){ //Tại đây, chúng ta có thể thiết lập thông tin thông qua hàm tạo throw new AgeException("Tuổi cần phải nằm trong khoảng từ 18 đến 120 tuổi"); } System.out.println("Phạm vi tuổi của bạn là chính xác"); } } //Tùy chỉnh một ngoại lệ/** * 1. Nói chung, ngoại lệ tùy chỉnh của chúng ta kế thừa RuntimeException * 2. Nghĩa là, biến ngoại lệ tùy chỉnh thành ngoại lệ thời gian chạy. Khi có lợi, chúng ta có thể sử dụng cơ chế xử lý mặc định * 3. Thuận tiện hơn */ class AgeException extends RuntimeException{ public AgeException(String message){ super(message); } }
Sự khác biệt giữa throw và throws
|
ý nghĩa |
Vị trí |
Những điều đằng sau |
ném |
Một cách xử lý ngoại lệ |
Khai báo phương thức |
Loại ngoại lệ |
ném |
Từ khóa để tạo thủ công các đối tượng ngoại lệ |
Trong thân phương thức |
Đối tượng ngoại lệ |
Cuối cùng, bài viết này về Java Basics - Exceptions kết thúc tại đây. Nếu bạn muốn biết thêm về Java Basics - Exceptions, vui lòng tìm kiếm các bài viết trên CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!