Java中的非常

张春  论坛元老 | 2025-4-12 23:49:49 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1575|帖子 1575|积分 4725

媒介
在编程的时候,不免会遇到一些特别情况,这大概会导致中止,这时候就要想着在运行的过程中能不能将这个问题捕获到,方便后面办理,这时候就要引入非常这个概念了

一 非常的概念

Java中将在代码执行过程中不正常的步伐称为非常

Throwable:是非常体系的顶层类,其派⽣出两个⼦类Error和Exception
Error(错误):指的是Java虚拟机⽆法办理的严峻问题,⽐如StackOverflowError和OutOfMemoryError,通常是JVM虚拟机内部问题
Exception(非常):非常产⽣后步伐员可以通过代码进⾏处置惩罚,使步伐继承执⾏
我们通常把Exception称为非常,Error是错误
例如:
算数非常
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         System.out.println(10/0);
  4.     }
  5. }
复制代码
除数不可以为0
运行结果中编译器会报出ArithmeticException算数非常

空指针非常
  1. //空指针异常
  2. public class Test {
  3.     public static void main(String[] args) {
  4.         int[] arr = null;
  5.         System.out.println(arr.length);
  6.     }
  7. }
复制代码
这里的arr数组是空的,不可以求其数组长度
NullPointerException空指针非常

数组下标访问非常
  1. //数组下标越界访问异常
  2. public class Test {
  3.     public static void main(String[] args) {
  4.         int[] arr = new int[3];
  5.         System.out.println(arr[3]);
  6.     }
  7. }
复制代码
这里的下标是[0,2],没有3下标,这时候会出现数组下标访问非常
ArrayIndexOutOfBoundsException数组下标越界访问非常

非常的分类

Java中主要分为编译时非常和运行时候非常
编译时非常(受检查非常)
字如其名,也就是在编译时候发生的非常,也叫受检查非常
   在没有运行编译器也会用红色波浪线提示
  例如:

这里子类重写Object父类的方法clone方法
这里说这个非常为举行捕获出来
如果没有捕获或者说明这里就会报错
下面时运行的结果,就算没有运行编译器也会用红色波浪线提示

像下面如许举行声明白就不会报错了
  1. public class Person{
  2.     private String name;
  3.     public int age;
  4.     @Override
  5.     //这里进行异常的声明或者捕获
  6.     protected Object clone() throws CloneNotSupportedException {
  7.         return super.clone();
  8.     }
  9. }
复制代码
运行时非常(非受查非常)
代码运行的时候编译器就会报错,在编译时并不会报错
RunTimeException以及其⼦类对应的非常,都称为运⾏时非常NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException等等,这些非常只有在运行时候才会报错,编译时可以通过的,这就是与编译时非常的区别
非常的处置惩罚

throws非常的声明

throws就是在方法中声明大概会出现的非常,用来提示编译者,但是这个只是声明,并不是将其处置惩罚
   修饰符 返回值类型 ⽅法名(参数列表) throws 非常类型1,非常类型2 等等
{ }
  1. public class Test {
  2.     public static void fun(int[] arr)throws Exception{
  3.         System.out.println(arr.length);
  4.     }
  5.     public static void main(String[] args) throws Exception{
  6.         int[] arr = null;
  7.         fun(arr);
  8.     }
  9. }
复制代码

这里只是声明白非常并没有处置惩罚,相当于只是将这个非常逐渐传递下去,并没有得到真正的办理
就像这里主函数调用了含有非常声明的方法,主函数也要举行声明,相当于谁利用这个方法都要声明
如果不声明编译器就会报错

  1. 1.throws必须跟在⽅法的参数列表之后
  2. 2. 声明的异常必须是Exception或者Exception的⼦类
  3. 3. ⽅法内部如果抛出了多个异常,throws之后必须跟多个异常类型
  4. 4. 如果声明多个异常是同一个父类,可以直接声明父类一异常
  5. 5. 但是throws并么有处理异常,只是仅仅声明了
复制代码
throw非常处置惩罚

   throw new 非常类型();
  1. public class Test {
  2.     public static void fun(int[] arr,int index){
  3.         if(arr==null){
  4.             throw new NullPointerException("空指针异常");
  5.         }
  6.         if(index<0||index>=arr.length){
  7.             throw new ArrayIndexOutOfBoundsException("数组下标越界异常");
  8.         }
  9.         System.out.println("后面的代码");
  10.     }
  11.     public static void main(String[] args) {
  12.         int[] arr = {1,2,3};
  13.         fun(arr,3);
  14.     }
  15. }
复制代码
这里一旦非常抛出,后面的代码就不会执行了,就像这里的3是超过数组下标,以是这里会抛出数组下标非常,后面的代码不会执行
运行结果如下

  1. 1.throw必须在方法内部
  2. 2.如果是RunTimeException或者其子类可以不用处理这些会在运行时由JVM来处理
  3. 3.异常一旦抛出,后面的代码就不会执行了
复制代码
try - catch捕获非常

Java中为了捕获非常有了 try catch finally等关键字
  1. try{
  2. // 将可能出现异常的代码放在这⾥
  3. //这里要捕获的异常类型与try中的异常一致
  4. }catch(要捕获的异常类型 e){
  5. //异常处理完后,后面的代码会执行
  6. }catch(异常类型 e){
  7. // 对异常进⾏处理
  8. }finally{
  9. // finally中代码一定会执行
  10. }
复制代码
例如
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         try{
  4.             int[] arr = {1,2,3};
  5.             System.out.println(arr[3]);
  6.         }catch (NullPointerException e){
  7.             e.printStackTrace();//处理异常
  8.         }catch (ArrayIndexOutOfBoundsException e){
  9.             e.printStackTrace();
  10.         }
  11.         //异常被捕获以后后面的代码会正常执行
  12.         System.out.println("后面的代码执行了");
  13.     }
  14. }
复制代码
这里是下标越界的非常,被捕获了处置惩罚了,如果没有捕获,这里后面的代码就不会执行了
运行结果如下

例如下面如果没有捕获和处置惩罚非常,非常后面的代码不会执行

就像这里try中放的是出现的是数组下标访问非常,而我们这里捕获的是空指针非常,以是这里并不会处置惩罚非常,因今后面的代码就不执行了
那这时候可以在其后面放其大概出现非常的父类举行捕获,如许就不会出现如许的问题了
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         try{
  4.             int[] arr = {1,2,3};
  5.             System.out.println(arr[3]);
  6.         }catch (NullPointerException e){
  7.             e.printStackTrace();
  8.         }catch (Exception e){//可以捕捉所有异常,因为其是异常的父类
  9.             e.printStackTrace();
  10.         }
  11.         
  12.         System.out.println("后面的代码执行了");
  13.     }
  14. }
复制代码
这里的空指针非常和数组下标访问非常都是Exception的子类,可以在后面放父类非常,防止没有捕获到
运行结果如下

但是不发起只是用父类Exception来举行捕获,以是尽量将其放在末了举行捕获父类非常,用起来兜底,防止自己没有考虑全面
   try如果捕获到了非常,其try中后面的代码就不会执行了

  1. try - catch注意事项
  2. 1.try中的异常如果被捕获到了异常,try中异常之后的代码不会执行
  3. 2.catch捕获的异常与抛出类型的异常不匹配,异常就不会被捕获
  4. 3.异常之间也有父子关系,捕获子类异常在捕获父类异常之后
复制代码
finally关键字

有些时候我们需要一些代码是必须要执行到,无论是存在否非常,一些步伐都要执行,那因此就要引出finally关键字
  1. 语法格式:
  2. try{
  3. // 可能会发⽣异常的代码
  4. }catch(异常类型 e){
  5. // 对捕获到的异常进⾏处理
  6. }finally{
  7. // 此处的语句⽆论是否发⽣异常,都会被执⾏到
  8. }
复制代码
  1. public class Test {
  2.     public static void main(String[] args) {
  3.         try{
  4.             int[] arr = {1,2,3};
  5.             System.out.println(arr[3]);
  6.         }catch (ArrayIndexOutOfBoundsException e){
  7.             e.printStackTrace();
  8.         }
  9.         finally {
  10.             System.out.println("finally中的代码被执行了");
  11.         }
  12.         System.out.println("后面的代码执行了");
  13.     }
  14. }
复制代码
这里finally中的语句会执行,try-catch中的语句会执行
运行结果如下

既然都可以执行,那为什么还要finally语句呢
  1. public class Test {
  2.     public static int fun(){
  3.         Scanner scanner = new Scanner(System.in);
  4.         try {
  5.             int sc = scanner.nextInt();
  6.             return sc;
  7.         }catch (InputMismatchException e){
  8.             e.printStackTrace();
  9.         }finally {
  10.             System.out.println("finally中的代码");
  11.         }
  12.         System.out.println("最后面的代码");
  13.         scanner.close();
  14.         return 0;
  15.     }
  16.     public static void main(String[] args) {
  17.         int n = fun();
  18.         System.out.println(n);
  19.     }
复制代码
这里就算有return 语句,finally中代码一定会被执行,而try-catch-finally后面的代码不会执行了

  1. 1.先执行try中的代码
  2. 2.如果try中的代码有异常,那就在try中后面代码不会执行,在catch寻找是否有
  3. 与try中异常相匹配的
  4. 3.如果没有在catch中匹配到对应异常,如果没有异常将会向上传递
  5. 4.上层如果也没有处理异常,异常将会继续向上传递,一直到main函数为止
  6. 5.无论是否匹配到异常,finally中的代码都会被执行
复制代码
四 自定义非常

固然Java提供了很多非常,偶然候一些非常不能满足我们的需求,这是我们就可以自定义非常来满足需求
这里我们模仿实现一个用户名和密码的登录
  1. public class Test {
  2.     private String userId = "三三";
  3.     private String  password = "060610";
  4.     public void login(String userId,String password) {
  5.             if(!this.userId.equals(userId)){
  6.                 System.out.println("用户名错误");
  7.             }
  8.             if(!this.password.equals(password)){
  9.                 System.out.println("密码错误");
  10.             }
  11.         System.out.println("登录成功");
  12.     }
  13.     public static void main(String[] args) {
  14.         Test test = new Test();
  15.         test.login("三三","060610");
  16.     }
  17. }
复制代码
这里密码和用户名都精确,这里会登录乐成
运行结果如下

那我们可以在其用户名错误或者密码错误的时候抛出非常
当然可以,这时候我们就要自定义一个非常,然后继承Exception或者RunTimeException
下面是两个自定义非常类
  1. //继承基类异常
  2. //用户名异常
  3. //这里继承的是受查异常
  4. class UserIdException extends Exception{
  5.     public UserIdException(String message){
  6.         super(message);
  7.     }
  8. }
  9. //密码异常
  10. class PasswordException extends Exception{
  11.         public PasswordException(String message){
  12.             super(message);
  13.         }
  14. }
复制代码
Test类中的代码利用上面的自定义非常
  1. class UserIdException extends Exception{
  2.     public UserIdException(String message){
  3.         super(message);
  4.     }
  5. }
  6. class PasswordException extends Exception{
  7.         public PasswordException(String message){
  8.             super(message);
  9.         }
  10. }
  11. public class Test {
  12.     private String userId = "三三";
  13.     private String  password = "060610";
  14.     public void login(String userId,String password) {
  15.         try {
  16.             if(!this.userId.equals(userId)){
  17.                 throw new UserIdException("用户名错误"+userId);
  18.             }
  19.             if(!this.password.equals(password)){
  20.                 throw new PasswordException("密码错误"+password);
  21.             }
  22.             //如果没有异常就会登录成功
  23.             System.out.println("登录成功");
  24.         }catch (UserIdException e){
  25.             e.printStackTrace();
  26.         }catch (PasswordException e){
  27.             e.printStackTrace();
  28.         }
  29.     }
  30.     public static void main(String[] args) {
  31.         Test test = new Test();
  32.         test.login("三三","060610");
  33.     }
  34. }
复制代码
这里用户名和密码都精确,以是是登录乐成

如果用户名不对,就会爆出用户名非常,登录就不乐成

   自定义非常都是继承Exception或者RunTimeException
继承Exception就是受查非常(编译时非常)
继承RunTimeException就是非受查非常(运行时非常)
  到这里就结束了,预知后事如何,请听下回分解

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表