java详细讲解之异常

异常

异常的概念与体系结构

在java中,将程序执行过程中发生的不正常行为称为异常。
1.算数异常

System.out.println(10/0);
//
Exception in thread"main" java.ArithmeticException:/by zero

2.数组越界异常

int[] arr={1,2,3};
System.out.println(arr[100]);
//
Exception in thread "main"java.langArrayIndexOutOfBroundsException:100

3.空指针异常

int[] arr=null;
System.out.println(arr.length);
//执行结果
Expection in thread "main"java.labg.NullPointerException

java中不同类型的异常,都有与其对应的类来进行描述。

1.Throwable:是异常体系的顶层端,其派生出两个重要的子类:Error和Exception
2.Error:指的是java虚拟机无法解决的严重问题,比如:JVM的内部错误,资源耗尽
3.Exception:异常产生后程序员可以通过代码进行处理,使程序继续进行。

异常的分类

1.编译时异常

public class Person{
  private String name;
  private Strinf gender;
  int age;
  //想要让该类支持深拷贝
  public Person clone(){
    return (Person)super.clone();
    }
 }

2.运行时异常
在程序执行期间发生的异常称为运行时异常,也称为非受检查异常。
RunTimeException以及子类对应的异常,都称为运行时异常。

异常的处理

防御式编程

错误在代码中是客观存在的,因此我们要让程序出现问题及时通知
1.LBY:在操作之前就做充分检查,即:事前防御型

boolean ret=flase;
ret =登陆游戏();
if(!ret){
   处理登陆游戏错误;
   return;
   }
   ret=开始匹配();
   if(!ret){
   处理匹配错误;
   return;
   }
   ret=游戏确认();
   if(!ret){
   处理游戏确认错误;
   return ;
   }
   ret=选择英雄();
   if(!ret){
   处理选择英雄错误;
   return;
   }

缺陷:正常流程和错误流程代码混在一起
2.EAFP:事后认错型

try{
登陆游戏();
开始匹配():
游戏确认():
选择英雄():
}
cash(登录游戏异常){
  处理登录游戏异常;
  }cash(开始匹配异常){
  处理匹配异常;
  }cash(游戏确认异常){
  .....

异常处理主要五个关键字:throw,try,catch,final,throws

异常抛出

在编写程序时,如果程序中出现错误,此时需要将错误的信息告诉调用者

throw new XXXException(“异常产生的原因”);

[需求]实现一个获取数组中任意元素的方法

public static int getElement(int[] array,int index){
  if(null==array){
  throw new NullPointerException(“传递的数组为null");
  }
  if(index<0||index>=array.length){
    throw new ArrayIndexOutOfBroundsException("传递的数组下标越界");
    }
    return array[index];
}
   public static void main(String[] args){
     int[] array={1,2,3};
     getElement(array,3);
 }

【注意事项】
1.throw必须写在方法体内部
2.抛出对象必须是Exception或者是Exception的子类对象
3.异常一旦抛出,其后的代码不会执行

异常的捕获

异常声明throws

处在方法声明时参数列表之后,当方法体跑出异常编译时异常,用户不象处理该异常,此时可以借助throws将异常抛给方法调用者来处理,即当前方法不处理异常提醒方法的调用者处理。

语法格式
修饰符 返回类型 方法名(参数列表)throws异常类型1,异常类型2…{
}

需求:加载指定的配置文件config.ini

public class Config{
  File file;
  /*
  FileNotFoundException:编译时异常,表明文件不存在
  public void OpenConfig(String filename)throws FileNotFoundException{
  if(filename.equals("config.ini"){
  throw new FileNotFoundException("配置文件名字不对");
  }
  //打开文件
  }
  

1.throw必须跟在方法体的参数列表之后
2.声明的异常必须是Exception或者Exception的子类
3.方法体内部如果抛出异常,throw之后必须跟多个异常类型。之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可。
4.调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用throws抛出

try-catch捕获或处理

throws对异常并没有真正处理,而是将异常报告给抛出异常的调用者。

语法格式:
try{
//将可能出现的异常的代码放这里
}catch(要捕获异常类型 e){
//如果try中的代码出现异常,此处catch捕获时异常类型与try中抛出异常类型一致时,或者try抛出异常基类时,会捕获
}[catch(异常类型 e){
//对异常进行处理
}finally{
此处代码一定会执行
}]

注意:
1【】中可表示选项,可以添加,不添加
2 try中的代码可能会抛出异常,也可能不会
需求:读取文件,如果配置文件名字不是指定文件名。抛出异常

public class Config{
    File file;
    public void openConfig(String filename)throws FileNotFoundException{
    if(!filename.equals("config.ini"){
    throw new FileNotFoundException("配置文件名字不对");
    }
    //打开文件
    }
    public void readConfig(){
      }
    public static void main(String[] args){
     Config config=new Config();
     try{
        config.openConfig("config.txt");
        System.out.println("打开文件成功");
        }cash(IOException e){
        //异常的处理方式
        //System.out.println(e.getMessage());//只打印异常
        //System.out.println(e);//打印异常类型:异常信息
        e.printStackTrace()://打印信息最全面
        }
```b
【注意事项】
1.try块内抛出异常位置之后的代码将不会被执行
2.如果抛出异常类型与catch时异常类型不匹配,即异常不会被捕获
```java
public static void main(String[] args){
 try{
 int[] array={1,2,3};
 System.out.println(array[3]);//此时会抛出异常
 }catch(NullPointerException e)//捕获时候的是空指针异常
 e.printlnStackTrace();
 }
 System.out.println("后续代码“);
 }

3.try中可能会抛出多个不同的异常对象,必须用多个catch来捕获

public static void main(Stirng[] args){
   int[] arr={1,2,3};
   try{
    System.out.println("before");
    //arr=null;
    System.out.println(arr[100]);
    System.out.println("after");
    }catch(ArrayIndexOutOfBoudsException e){
     System.out.println("这是个数组下标越界异常");
     e.printStackTrace();
     }catch(NullPointerException e){
     System.out.println("这是个空指针异常"):
     e.prinyStackTrace();
     }
     System.out.rpintln("after try catch");
     } 

如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch

public static void main(String[] args){
  int[] arr={1,2,3};
  try{
    System.out.println("before");
    arr=null;
    System.out.println("after");
    }catch(Exception e){
    //Exception 可以捕获所有异常
    e.printStackTrace();
    }catch(NullPointerException e){
    e.printtackTrace();
    }
    System.out.println("after try catch");
    }

finally

在写程序,有些特定的代码,无论程序是否发生异常,都需要执行、在程序正常或者异常退出时,必须要对资源进行回收。

语法格式
try{
可能会发生异常的代码
}catch(异常类型 e){
//对捕获到的异常进行处理
}finally{
//一定会执行
}
如果没有抛出异常,或异常处理捕获,会执行代码

public static void main(String[] args){
try{
  int[] arr={1,2,3};
  arr[100]=10;
  arr[0]=10;
  }catch(ArrayIndexOutOfBoundsException e){
    System.out.println(e);
    }finally{
      System.out.println("finally中的代码一定会执行");
      }
      System.out.println("如果没有抛出异常,或者异常被处理了,try-catch后代码也会被执行");
      }

问题:既然finally和try—catch-finally后·的代码都会执行,为什么还有finally
需求:实现getData方法,内部输入一个整形数字,然后将数字返回,并在main1方法返回

public class TestFinally{
  public static int getData(){
    Scanner sc=null;
    try{
       sc=new Scanner(System.in);
       int data =sc.nextInt();
       return data;
       }cash(InputMismatchException e){
       e.printStackTrace();
       }finally{
         System.out.println("finally中代码");
         }
         System.out.println("Try-catch-finally之后代码");
         if(null!=sc){
         sc.close();
         }
         return 0;
         }
         public static void main(STring[] args){
         int data=getData();
         System.out.println(data);
         }
      }

异常处理流程

public static void main(String[] args){
 try{
 func();
 }catch(ArrayindexOutOfBoundsException e){
   e.printStackTrace();
   }
  System.out.println("after try catch");
 }
 public static viod func(){
   int[] arr={1,2,3};
   System.out.println(arr[100]);
   }

【总结】

  • 程序先执行try中的代码
  • 如果try中的代码出现异常,就会结束try代码,看和catch中的异常是否匹配
  • 如果找到匹配异常的类型,会执行catch代码
  • 如果没有找到,会将异常向上传递
  • 无论是否找到匹配类型,finally中的代码都会被执行
  • 如果上层也没有处理,就再向上传递
  • 一直到main方法后会给JVM来进行处理

自定义异常类

Java中虽然已经内置丰富的异常类,但并不完全表示实际开发中所遇到的一些异常。
例如:实现用户登录

public class Login{
  private String useName="admin";
  private String password="123456";
  public static voif loginfo(String userName,Stringpassword){
   if(!this.useNAme.equals(userName)){
     }
    if(!this.password.equals(password)){
}
    System,out.println("登陆成功");
    }
    public static void main(String[] args){
    loginfo("admin","123456");
    }
  }

此时我们在处理用户名密码错的时候可能就需要抛出两个异常,我们可以基于已有的异常类型进行拓展。
具体方式:
1.自定义异常类,然后继承自Exception或者RunTimeException
2.实现一个带有String类型参数的构造方法

class UserNameException extends Exception{
 public UserNameException(String message){
  super(message);
  }
}
 class PasswordException extends Exception{
  public PasswordException(String mesage){
   super(message);
   }
 }

此时我们login代码可以变成

public class Login{
   private String uesrName="admin";
   private String password="123456";
public static void loginfo(String userName String password){
   throws UserNameException,PasswordException{
 if(!userName.equals(password)){
   throws new UserNameException("用户名错误"):
 }
 if(!password.equals(password)){
 throws new PasswordException("用户名错误");
 }
 System.out.println("登陆成功");
 }
 public static void main(String[] args){
 try{
 }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以用一些例子来讲解一下Java异常处理。 Java 异常处理的主要目的是帮助我们在程序运行时避免出现错误的情况。在 Java 中,异常通常包括两种类型:checked exceptions 和 unchecked exceptions。 Checked exceptions 是指在编译时可以发现的异常。例如,在读取一个不存在的文件时,Java 会抛出一个叫做 FileNotFoundException 的 checked exception。在处理 checked exceptions 时,我们必须使用 try-catch 语句块来捕获和处理异常。 下面是一个示例代码: ```java try { File file = new File("someFile.txt"); FileReader fr = new FileReader(file); } catch (FileNotFoundException e) { System.out.println("File not found: " + e.getMessage()); } ``` 在这个示例代码中,我们尝试读取一个叫做 "someFile.txt" 的文件,但是如果该文件不存在,Java 就会抛出一个 FileNotFoundException 异常。在 try 语句块中,我们创建了一个 File 对象和一个 FileReader 对象,但是如果出现异常,就会跳转到 catch 语句块中进行处理。在 catch 语句块中,我们输出了一个错误信息,该信息包含了异常详细信息。 Unchecked exceptions 是指在运行时才能发现的异常。例如,在尝试除以零时,Java 会抛出一个叫做 ArithmeticException 的 unchecked exception。 下面是一个示例代码: ```java int a = 10; int b = 0; try { int c = a/b; } catch (ArithmeticException e) { System.out.println("Cannot divide by zero: " + e.getMessage()); } ``` 在这个示例代码中,我们尝试将变量 a 除以变量 b,但是如果变量 b 的值为零,Java 就会抛出一个 ArithmeticException 异常。在 try 语句块中,我们进行了除法运算,但是如果出现异常,就会跳转到 catch 语句块中进行处理。在 catch 语句块中,我们输出了一个错误信息,该信息包含了异常详细信息。 总而言之,Java 异常处理可以帮助我们在程序运行时避免出现错误的情况,并且可以通过 try-catch 语句块来捕获和处理异常。在编写 Java 代码时,我们应该注意处理可能出现的异常,以确保程序的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿在线码字

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值