JAVA 异常处理

java的异常处理

程序运行时发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。异常发生时,是任程序自生自灭,立刻退出终止。

1 Scanner sc=new Scanner(System.in);
2 String ss=sc.nextLine();
3 int kk=Integer.parseInt(ss);
4 System.out.println("用户输入数据为:"+kk);
5
6 //用户输入abc
7 /*
8 则执行结果为:
9 Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
10 at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
11 at java.lang.Integer.parseInt(Integer.java:580)
12 at java.lang.Integer.parseInt(Integer.java:615)
13
14
at test.A.main(A.java:9)
*/

程序员真理:程序会出错
出错不是问题,关键是出错之后,错误如何处理?谁处理?
程序可以从错误中恢复吗?恢复不了就崩溃么?
意外产生和处理过程概述
运行时有许多因素引起出错,硬件失败,除法溢出,数组下标越界。
出错的位置都在方法Method里
出错后方法生成一个Exception对象,并把它交给JVM。这个对象里包括许多信息:错误类型,错误位置。JVM负责处理Exception对象
这种生成Exception对象并交给系统的过程叫抛出意外throwing an exception
一个方法抛出意外后,JVM就试图在“调用栈”里找能处理这个类型Exception对象的方法。找到就执行,找不到程序中止
出错的处理方式
以前正常流程代码和问题处理代码相结合。现在将正常流程代码和问题处理代码分离,以提高阅读性。

1 public static int bbb(int k) {
2 if (k > 100) {
3 //输出正常处理
4 return 0;
5} else if (k > 10) {
6 return -3;
7 } else if (k > 0) {
8 return -2;
9} else {
10return -1;
11}
12
13}可以根据返回值判断程序的执行情况,如果>=0表示正常执行完毕,如果<0,则返回不同的负值表示不同的运行情况。调用方法时可以根据不同的返回值进行不同的处理
14
15java中引入异常对象的目的在于给调用方更加详细的出错说明,以达到异常处理和正常代码分离,并且按照不同的异常进行处理的目的

其实异常就是Java通过面向对象的思想将程序中的问题封装成了对象,用异常类对其进行描述。1、不同的问题用不同的类进行具体的描述。2、问题很多,意味着描述的类也很多,将其共性进行向上抽取就形成了异常体系
异常
Java异常是Java提供的用于处理程序中错误的一种机制
所谓错误是指在程序运行的过程中发生的一些异常事件。如除0溢出、数组下标越界、所需要读取的文件不存在
设计良好的程序应该在异常发生时提供处理这些错误,使得程序不会因为异常的发生而阻断或者产生不可预见的结果
Java程序的执行过程中如果出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并经被提交给Java运行时系统,这个过程称为抛出异常throw
当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这个过程称为捕获异常
Java异常处理的关键字有throws、throw、try、catch、 nally共5个关键字
异常用途
异常就是在程序运行时由代码所产生的不正常状态。换句话说,异常就是一个运行时不支持异常处理的计算机语言中,错误必须被人工进行检查和处理,这显然麻烦而低效
Java语言提供了异常处理机制,为方法的异常终止和出错处理提供了清楚的接口
1、用来在发生运行异常时告诉程序如何控制自身的运行,以防止错误的进一步恶化
2、每个方法必须对他可能抛出的异常进行预先声明,在定义方法时,必须声明这个方法可能会抛出哪一种或几种异常
异常的分类
JavaSE中定义了很多异常类,这些类可以对应各种各样可能出现的异常事件。

1 int k=0;
2 System.out.println(100/k);
3 System.out.println("end...");
4
5允许则会发现出现报错ArithmeticException,同时显示出错行号,但是看不到end...的输出

在这里插入图片描述
Throwable类是Java异常类型的顶层父类,一个对象只有是 Throwable 类的(直接或者间接)实例,他才是一个异常对象,才能被异常处理机制识别
在这里插入图片描述
Java异常可以分为3大类
所有异常对象的父类为Throwable—Object
1、Error及其子类:错误,一般指的是虚拟机的错误,是由Java虚拟机生成并抛出,程序不能进行处理所以也不加处理,例如OutOfMemoryError内存溢出、调用栈溢出StackOverFlowError

1public static void pp(){
2 System.out.println("this is pp....");
3 pp();
4}

在控制台上显示Exception in thread main java.lang.StackOver owError
2、RuntimeException及其子类:运行时异常(非受检型异常),是由于编程bug所导致,希望越早发现越好,所以不进行处理,直接中断报错即可,编程人员针对报错信息修改程序bug来解决问题。
面试题:请说出至少5种常见的异常类型,用于检查应试者平常的编码量
常见的第一种运行时异常:ArithmeticException算术异常,就是执行数学计算时产生的非正常情况,如除以0

1 int k=0;
2 System.out.println(10/k);

这里明显是一个编程的bug,因为除法计算要求分母非0。修正bug,这里进行分母为0的处理

1 int k = 0;
2 if (k != 0)
3System.out.println(10 / k);
else
System.out.println("除数为0,不能执行除法计算");
System.out.println("end.....");

常见的 第二种运行时异常:NullPointerException空指针异常(试图访问null对象的引用)

1 Object obj=null;
2 System.out.println(obj.toString());
//注意如果直接输出反而没有异常System.out.println(obj)

这里出错的原因是调用对象的方法之前没有进行非空判断,所NullPointerException

1 Object obj = null;
2 if (obj != null)
System.out.println(obj.hashCode());
else
System.out.println("obj没有具体对象");

常见的 第三种运行时异常:IndexOutOfBoundsException下标出界

1 int[] arr=new int[3];
2 //异常的原因是访问数组的下标超出允许的范围[0,arr.length]
3 System.out.println(arr[3]); //ArrayIndexOutOfBoundsException
4 //异常的原因是通过下标访问字符串中字符时,超出了下标允许的范围[0,str.length()]
5 String str="abcd";
6 System.out.println(str.charAt(5));//StringIndexOutOfBoundsException

解决方法是通过下标访问时应该判定下标的取值是否合法

1 int[] arr = new int[] { 1, 2, 3, 4 };
2 int index = 0;
3 if (index >= 0 && index < arr.length)
4
System.out.println(arr[index]);// 避免ArrayIndexOutOfBoundsException
5
6 String str = "asdfasdf";
7 if (index >= 0 && index < str.length())
8
System.out.println(str.charAt(index));// 避免StringIndexOutOfBoundsException

常见的 第四种运行时异常:ClassCastException试图把一个对象转换成非法类型

1 Object dd=new Date();
2 //异常的原因是dd是Date类型,这个类型和Random没有任何关系,所以不能进行强制类型转换
3 Random rr=(Random)dd; //ClassCastException
1 //这里不会异常,因为学生是人的子类,所以任何一个学生都是人类
2 Object dd=new 学生();
3 人 obj=()dd;
4
5
//但是这样操作也会出问题。异常的原因是:人是学生类的父类,不是每个人都是学生,所以不能进行强制类型转6 Object dd=new();
7 学生 s1=(学生)dd;//ClassCastException

解决方案:进行类型强制转换之前,应该对变量类型进行判断,如果合法才进行类型的转换

1if(obj!=null && obj instanceof Random){
2Random r=(Random)dd;
3}

常见的第五种运行时异常:NumberFormatException数据格式异常,一般出现在数据类型转换中

1String ss = "123.456";// 字符串,其中内容为浮点数
2
  /*
3 * 数据类型转换有2种写法:
4 * Integer.valueOf("内容"):Integer
5 * Integer.parseInt("内容"):int
6 */
7Integer kk = Integer.valueOf(ss);// NumberFormatException数据的格式错误,数据是浮点数格式,不是整数
8int k2 = Integer.parseInt(ss);
9
10int k3=Integer.valueOf(ss);//自动装拆箱操作支持

进行数据类型转换之前可以进行格式验证

1String ss = "123456";// 字符串,其中内容为浮点数
2
// 因为没有正则式
3 boolean bb = true;
4 for (int i = 0; i < ss.length(); i++) {
5char cc = ss.charAt(i);
6//这里没有考虑+-号,如果考虑还需要处理+-两个符号
7if (cc < '0' || cc > '9') {
8bb = false;
9break;
10}
11 }
12 if(bb){
13int kk=Integer.valueOf(ss);
14System.out.println(kk);
15}else{
16System.out.println("数据格式错误!");
17}

这里进行数据的合法性验证后再进行数据类型转换比较繁琐,所以最终的解决方案是使用try/catch语法结果,针对出现问题后进行处理

1 int kk=0;
2 try{
3
4kk=Integer.parseInt(s1); //如果没有问题则进行数据类型转换
}catch(NumberFormatException e){
5kk=100;//如果数据不合法,则使用这个默认值
6 }
7 System.out.println(kk);

3、Exception及其子类中除了RuntimeException及其子类之外的其它异常:受检型异常(非运行时异常),这类异常属于明知道可能出现,但是没有办法杜绝的异常。这类异常一般采用try/catch或者throws声明抛出的方式进行异常处理,当程序出现了非正常情况,尽量保证程序正常结果,而不是立即中断
受检型异常:明知道存在这种异常的可能,但是没有办法杜绝,所以必须进行编码异常处理
非受检型异常:这种异常不需要进行处理,发现的越早越好
命令行上的数据录入
异常的捕获和处理
语法规则:

1try{
2try代码段中包含可能产生异常的代码,有人称为陷阱代码,在执行过程中如果出现了异常,则异常之后的java语句不会执行。转而执行catch部分的代码
3} catch(SomeException e){
4可以写多个try后可以跟一个多个catch代码段,针对不同异常执行不同的处理逻辑。当异常发生时,程序会中止当前的流程,根据获取异常的类型去执行响应的代码段。注意异常类型判定时是从上向下逐个判断的。
5} finally{
6finally代码是无论是否发生异常都会执行的代码
7}
1 Integer kk=null;
2 try{
3 String str="123.456";
4 //由于str参数数据不合法,不是整数,所以这里异常NumberFormatException
5 kk=Integer.parseInt(str);
6System.out.println("数据转换结束");//上句出现异常,这里就不会执行
7} catch(Exception e){//出现异常后进行类型判断,如果是这种异常则执行这里的代码段,可以有多个捕捉异8System.out.println("出现了错误:"+e.getMessage()); //e.getMessage():String用于获取异常的提示信息
9e.printStackTrace(); //在控制台(标准错误流System.err)上输出异常调用栈
10 }
11 System.out.println("转换结果为:"+kk);

注意:
try块中的局部变量和catch块中的局部变量(包括异常变量),以及 nally中的局部变量,他们之间不可共享使用
Java采用的是终结式异常处理机制,java中异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方去。也就是说:当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。
try{}后面必须跟一个 nally或者catch,其中有个特殊写法可以省略后面的 nally和catch
Java异常处理
try–用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。 catch–用于捕获异常。catch用来捕获try语句块中发生的异常。 nally-- nally语句块总是会被执行。它主要用于回收在try块里打开的资源(如数据库连接、网络连接和磁盘文件)。只有 nally块,执行完成之后,才会执行try或者catch块中的return或者throw语句,如果 nally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。 throw-- 人为编程实现抛出异常。
在这里插入图片描述
throws–用在方法签名中,用于声明该方法可能抛出的异常,要求谁调用谁处理这个异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。
在这里插入图片描述
try语句
try语句指定一段代码,该段代码就是一次捕获并处理异常的范围
在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做响应的处理
如果没有异常产生,所有的catch代码段都能略过不执行

1 Integer kk=null;
2 try{
3 String str="123.456";
4 //由于str参数数据不合法,不是整数,所以这里异常NumberFormatException
5 kk=Integer.parseInt(str);
6 System.out.println("数据转换结果");//如果上句出现异常,则立即会中断代码执行,这里不会有执行机会
7} catch(NumberFormatException e){
8 //异常处理中catch只匹配一次,匹配之后的后续catch会被忽略。注意这里不是最佳匹配
9 System.out.println("数据格式错误!");
10} catch(Exception e){
11System.out.println("出现了错误:"+e.getMessage());
12 }
13 System.out.println("准换结果为:"+kk);

catch语句
在catch语句块中是对异常进行处理的代码,每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象,同时允许异常的继续抛出
catch只匹配成功一次即可,注意不是最佳匹配,例如交换Exception和NumberFormatException的位置,这里就会语法报错,报错的提示信息为Unreachable catch block for NumberFormatException. It is already handledby the catch block for Exception,含义是catch(NumberFormatException e)是不可达语句,NumberFormatException是Exception的子类。
强调:在编写多个catch时,小异常一定在大异常之前。
在这里插入图片描述

1 Integer kk=null;
2 try{
3 String str="123.456";
4 kk=Integer.parseInt(str);
5 System.out.println("数据转换结束");
6} catch(NumberFormatException e){
7 System.out.println("数据格式错误!");
8 //继续抛出异常,不再是直接消费处理掉了,导致的结果是try之后的代码并没有得到执行
9 throw new Exception(e.getMessage());
10//throw e;在用在方法上throws声明抛出,因为NumberFormatException是运行时异常
11//throw new Exception(""); 需要在方法上声明抛出,因为Exception是受检型异常
12} catch(Exception e){
13System.out.println("出现了错误:"+e.getMessage());
14 }
15 System.out.println("转换结果为"+kk);

在catch中声明的异常对象封装了异常发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息
getMessage():String用于获取有关异常事件的信息,一般是异常信息的描述,【For input string:“123.456”】
toString():String,输出格式为【java.lang.NumberFormatException: For input string: “123.456”】
printStackTrace():void用来跟踪异常事件发生时执行堆栈的内容,注意:这里的输出默认采用错误流System.err进行输出,如果还使用了System.out进行输出,则不能保证显示顺序
在这里插入图片描述
注意:使用printStackTrace输出调用栈使用的是System.err输出报错信息,不是编程使用的System.out,所以输出顺序有可能和预计不一致
常见的3种输出异常的用法
System.out.println(e);//java.lang.ArithmeticException: / by zero
System.out.println(e.getMessage()); // / by zero
e.printStackTrace(); 调用栈

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值