什么是异常?


异常其实说白了,就是程序中可能出现的问题,Jvm告诉你,你去解决。
其实从1995年java就在一直收集各种各样的异常问题,java把这一个个异常变成对象。jvm读到异常,创建一个对象,然后返回给你异常信息,异常信息就是报错红线

如图,这就是一个异常,main指的是顺序走下来在你的主线程中出现了异常,InputMismatchException就是异常封装的对象,灰色字体是工具类的资源路径,蓝色字体是你程序中发生异常的位置,我们检查异常一定要先看蓝色的部分。

那么这个异常是怎么产生的呢?

    public static void main(String[] args){haha();System.out.println("程序执行完毕 , 正常结束");}private static void haha() {Scanner input = new Scanner(System.in);System.out.println("请输入一个数字");int x = input.nextInt();System.out.println("请再输入一个数字");int y = input.nextInt();System.out.println(x / y);System.out.println("处理完毕");System.out.println("亲, 除数不能为0");}

原因:我们输入的时候没有输入数字而是输入了字母,所以导致了异常的发生。这时JVm给我们抛出了一个异常,如果我不想继续抛出则需要自己处理异常,这时就需要用到try catch

处理异常

如果要想对异常进行处理,则必须采用标准的处理格式,处理格式语法如下: try{
// 有可能发生异常的代码段
}
catch(异常类型1 对象名1){
// 异常的处理操作

}catch(异常类型2 对象名2){
// 异常的处理操作
} …
finally{
// 异常的统一出口
}
其实你把try catch 可以理解为if语句如果try发现异常就执行 catch(里面是对意料到的异常处理操作)

try+catch处理流程

1.一旦发生一个异常,则系统会自动产生一个异常类的实例化对象。
2.那么,如果异常发生在try语句,则就会自动去找到匹配的catch语句去执行。如果没有发生在try语句中,则会将异常抛出。
3.所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。

异常处理格式

多异常捕获的注意点:
1、 捕获更粗的异常不能放在捕获更细的异常之前。
2、 如果为了方便,则可以将所有的异常都使用Exception进行捕获。

(图2)
特殊的多异常捕获写法 catch(异常类型1 |异常类型2 对象名){
//表示此块用于处理异常类型1 和 异常类型2 的异常信息
}.


/*** 处理多异常的格式 1*/
public class Demo2 {public static void main(String[] args){haha();System.out.println("程序执行完毕 , 正常结束");}private static void haha() {try {Scanner input = new Scanner(System.in);System.out.println("请输入一个数字");int x = input.nextInt();System.out.println("请再输入一个数字");int y = input.nextInt();System.out.println(x / y);System.out.println("处理完毕");}catch(InputMismatchException e){System.out.println("必须输入数字啊, 帅哥");}catch(ArithmeticException e){System.out.println("除数不能为0啊 , 帅哥");}}
}

如上图,如果x/y发生了异常,那么下面那句话就不会打印输出

package com.java.demo1;import java.util.InputMismatchException;
import java.util.Scanner;/*** 处理多异常的格式 2   了解*/
public class Demo3 {public static void main(String[] args){haha();System.out.println("程序执行完毕 , 正常结束");}private static void haha() {try {Scanner input = new Scanner(System.in);System.out.println("请输入一个数字");int x = input.nextInt();System.out.println("请再输入一个数字");int y = input.nextInt();System.out.println(x / y);System.out.println("处理完毕");}catch(InputMismatchException|ArithmeticException e){System.out.println("输入有误");}}
}
package com.java.demo1;import java.util.InputMismatchException;
import java.util.Scanner;/*** 处理多异常的格式 3    常用*/
public class Demo4 {public static void main(String[] args){haha();System.out.println("程序执行完毕 , 正常结束");}private static void haha() {try {Scanner input = new Scanner(System.in);System.out.println("请输入一个数字");int x = input.nextInt();System.out.println("请再输入一个数字");int y = input.nextInt();System.out.println(x / y);System.out.println("处理完毕");}catch(Exception e){//多态System.out.println("输入有误");}finally {//必然执行的异常统一处理出口//无论是否发生异常, finally必然执行.System.out.println("213123");}}
}

finally

在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生 了异常,最终都要执行此段代码。但也有几个特殊情况如电脑断电或者程序关闭,下面我们展示第二种

    public static void main(String[] args) {haha();}public static void haha(){try{int a = 10;int b = 0;System.out.println(a/b);}catch(Exception e){//退出JVMSystem.out.println("出现了异常");System.exit(0);}finally {System.out.println("锄禾日当午,汗滴禾下土");}}

如上图,程序执行完毕并没有打印“锄禾日当午,汗滴禾下土”这是为什么呢?
当我们try中的语句抛出异常时,catch进行捕获然后执行到System.exit(0)时程序就关闭了,所以我们无法执行finally里面的语句,但是前面的 System.out.println(“出现了异常”); 可以打印

package com.java.demo1;public class Demo5 {public static void main(String[] args) {haha();}public static void haha(){try{System.out.println("1");System.out.println("2");System.out.println("3");System.out.println("4");return;}catch(Exception e){}finally {System.out.println("锄禾日当午,汗滴禾下土");}}
}

上面这段代码的finally语句会不会执行呢?
答案是会的,当try中的四条输出语句打印完毕后,程序并没有立即执行return从而结束整个方法而是等待finally执行完毕才执行return。
下面还有几个例子

如上图,结果age为28,知道了执行return之前,还要等待finally执行完毕所以age被重新赋值为28.(注意:由于是new的对象Person所以在栈中存在Person对象的引用地址,return在等待时会赋值一份地址出来(此时的p是引用类型的),我们将来会return复制的内容,指向引用的对象,所以此时finally是顺着地址改变的对象值)
下面还有一种情况


如上图,此时return的值为10,那么为什么呢?
根据之前的描述我们知道了,return返回的是复制的备份,那么由于a是变量所以我们复制的就是a本身的值(a是基本类型),finally没有改变a的值。

异常体系结构

异常指的是Exception , Exception类, 在Java中存在一个父类Throwable(可能的抛出) Throwable存在两个子类:
1.Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。(系统觉得你处理不了的)
2.Exception:一般表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。(系统觉得你可以处理的)

如图我们看到在Exception类中下面还有两大类一个是受检查异常,还有一个是非受检查异常他们是什么意思呢?

受检查异常(非运行时异常):你的代码写出来就漂红的就异常
非受检查异常(运行时异常):你编写的时候看不出来,运行的时候有可能发生异常

throws

在程序中异常的基本处理已经掌握了,但是随异常一起的还有一个称为throws关键字,此关键字主要在方法的声明上使 用,表示方法中不处理异常,而交给调用处处理。
格式:返回值 方法名称()throws Exception{ }

   public static void shutdown(String text) throws IOException {Runtime.getRuntime().exec(text);}

如图所示,当执编译exec方法时,idea提示飘红,这时我们需要抛出一个异常,因为这是我们不能用try catch去解决的异常,换言之如果程序发生的异常我们无法解决,则需要使用throws抛给方法调用者。反之异常我们可以解决并且我们希望发生的异常不影响程序执行,那么我们就使用try catch处理异常

原则:如果该功能内部可以将问题处理,用 try,如果处理不了,交由调用者处理,这是用 throws
区别:
当前程序需要继续运行就 try
当前程序不需要继续运行就throws
举例:
感冒了就自己吃点药就好了,try
吃了好几天药都没好,结果得了 H7N9,那就得throws到医院去对人进行治疗
如果医院没有特效药,就变成 Error 了

throw

throw关键字表示在程序中人为的抛出一个异常,因为从异常处理机制来看,所有的异常一旦产生之后,实际上抛出 的就是一个异常类的实例化对象,那么此对象也可以由throw直接抛出。 代码: throw new Exception(“抛着玩的。”) ;

throw通常是程序员手动抛出的异常,那么为什么这样做呢?
比如你写一个方法别的程序需要调用,那么他可能调用你的方法会发生异常,这个时候你就需要吧这个异常主动的抛出去,让他去处理。是不是和throws很像,但其实还是有很大区别的。

区别1:

 throws:跟在方法声明后面,后面跟的是异常类名throw:用在方法体内,后面跟的是异常类对象名   
public static void method() throws ArithmeticException {// 跟在方法声明后面,后面跟的是异常类名int a=10;int b=0;if(b==0) {throw new ArithmeticException();用在方法体内,后面跟的是异常类对象名 }else {System.out.println(a/b);}}
}

区别2:

throws:可以跟多个异常类名,用逗号隔开throw:只能抛出一个异常对象名 
 public static void method() throws ArithmeticException,Exception {//跟多个异常类名,用逗号隔开int a=10;int b=0;if(b==0) {throw new ArithmeticException();// 只能抛出一个异常对象名}else {System.out.println(a/b);}}
}

区别3:

throws:表示抛出异常,由该方法的调用者来处理throw:表示抛出异常,由该方法体内的语句来处理

public class throwandthrows {public static void main(String[] args) {try {method();//由该方法的调用者来处理}catch (ArithmeticException e) {e.printStackTrace();}}public static void method() throws ArithmeticException {int a=10;int b=0;if(b==0) {throw new ArithmeticException();//由该方法体内的语句来处理}else {System.out.println(a/b);}}
}

区别4:

throws:throws表示有出现异常的可能性,并不一定出现这些异常throw:throw则是抛出了异常,执行throw一定出现了某种异常

我们向上面例子代码里throws一个IndexOutOfBoundsException异常,编译发现并没有报错,这就体现了throws表示有出现异常的可能性


public class throwandthrows {public static void main(String[] args) {try {method();}catch (ArithmeticException e) {e.printStackTrace();}}public static void method() throws ArithmeticException,IndexOutOfBoundsException {int a=10;int b=0;if(b==0) {throw new ArithmeticException();}else {System.out.println(a/b);}}
}

RuntimeExcepion与Exception的区别

注意观察如下方法的源码:
Integer类: public static int parseInt(String text)throws NumberFormatException

此方法抛出了异常, 但是使用时却不需要进行try。。。catch捕获处理,原因: 因为NumberFormatException并不是Exception的直接子类,而是RuntimeException的子类,只要是 RuntimeException的子类,则表示程序在操作的时候可以不必使用try…catch进行处理,如果有异常发生,则由JVM进 行处理。当然,也可以通过try catch处理。

自定义异常(了解)

虽然从1995年,java汇总了许许多多的异常并封装成了对象告诉我们。但我们在实际开发中,有一些异常需要我们人为的去编写,非共性的异常。我们自定义异常时需要注意,如果我们编写的异常继承了RuntimeException运行时异常(非受检异常)你抛出异常那么别人调用的时候出现异常不会飘红,如果非RuntimeException的异常(受检异常,直接继承Exception也算),你抛出了这个异常那么别人调用的时候代码就会飘红。(受检查的异常必须要抛出去或者trycatch,别人调用的时候要么抛出去要么try catch)

RuntimeException自定义异常

public class AgeRuntimeException extends RuntimeException{public AgeRuntimeException(String message) {super(message);}
}

如上图我们编写了一个异常类继承RuntimeException,调用父类的构造方法,用来自定义抛出异常的信息,大部分情况下我们也是这么做的。

public class Person {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {if(age<0 || age>180){AgeRuntimeException e = new AgeRuntimeException("年龄不合理");throw e;}else{this.age = age;}}
}

如上图我们在创建自定义异常类对象的时候就传入了要抛出异常的信息。

public class Demo {public static void main(String[] args) {Person p = new Person();p.setAge(-1);}
}

如上图如果我们年龄赋值不合规范那么结果就是:


红字部分就是我们传入的异常信息。

异常处理常见面试题

  1. try-catch-finally 中哪个部分可以省略?
    答: catch和finally可以省略其中一个 , catch和finally不能同时省略 注意:格式上允许省略catch块, 但是发生异常时就不会捕获异常了,我们在开发中也不会这样去写代码.
  2. try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗? 答:finally中的代码会执行 详解:执行流程: 1. 先计算返回值, 并将返回值存储起来, 等待返回 2. 执行finally代码块 3. 将之前存储的返回值, 返回出去; 需注意:1. 返回值是在finally运算之前就确定了,并且缓存了,不管finally对该值做任何的改变,返回的值都不 会改变 2. finally代码中不建议包含return,因为程序会在上述的流程中提前退出,也就是说返回的值不是try或 catch中的值3. 如果在try或catch中停止了JVM,则finally不会执行.例如停电- -, 或通过如下代码退出 JVM:System.exit(0);

异常你看这一篇就行了,全程白话很好理解(完结撒花)相关推荐

  1. CompletableFuture使用详解(全网看这一篇就行)

    Java8 CompletableFuture 用法全解_孙大圣666的博客-CSDN博客_completablefuture ​​​CompletableFuture使用详解(全网看这一篇就行)_代 ...

  2. Mysql完结汇总篇(18万字送给你),完结撒花

    hello大家好,我是黎杜,上一篇写了关于Mysql的日志篇,有兴趣的可以看一看,距离上一次的写完了JVM的调优所有部分:如何啃下JVM这座大山,完结撒花(完结篇),这些词也写完了关于Mysql的所有 ...

  3. Prettier看这一篇就行了

    点击上方关注 前端技术江湖,一起学习,天天进步 作者:陈龙 https://zhuanlan.zhihu.com/p/81764012 已获取作者授权,请勿未经允许转载. 0.前言 用了两年 Pret ...

  4. 使用anaconda安装pytorch——看这一篇就行了

    开门见山 我的电脑里有python编译器 如何装pytorch框架? 答--用anaconda进行安装 翻阅了n多的文章 发现一个真理 看得越多 越容易出问题 那这里我针对每一个需要实现的目的 只放一 ...

  5. C站学习导航,想用CSDN学习看我这篇就行了!

    大家好,我是辣条. 作为C站的博主,相信大家感受到了文章热榜上的"恐怖如斯",最低都是万字长文起步,热榜前几的文章都是几万字的,博主也是苦不堪言,文章字数上去了,质量却没有上去,你 ...

  6. MPP架构是什么?看这一篇就行了。。

    文章目录 MPP是什么 SMP- Symmetric Multi-Processor 对称多处理器结构 NUMA -Non-Uniform Memory Access 非一致存储访问结构 MPP -M ...

  7. 学会Linux,看完这篇就行了!

  8. 看完这篇你们团队的代码也很规范

    最近重构项目组件,看到项目中存在一些命名和方法分块方面存在一些问题,结合平时经验和 Apple官方代码规范 在此整理出 iOS 工程规范.提出第一个版本,如果后期觉得有不完善的地方,继续提出来不断完善 ...

  9. 细心看完这篇文章,刷新对Javascript Prototype的理解

    var person={name:'ninja'}; person.prototype.sayName=function(){return this.name; } 分析上面这段代码,看看有没有问题? ...

最新文章

  1. R-CNN(Rich feature hierarchies for accurate object detection and semantic segmentation)论文理解...
  2. xp系统c 语言命令重定向,Xp命令解释程序cmd.exe概述
  3. LeetCode 91. 解码方法
  4. Spring中的Bean是线程安全的么?
  5. SQL应用与开发:(七)数据操作 #183; 查 #183; (一)常规型
  6. 显卡4k性能测试软件,碰上UHD都得跪 AN新一代显卡4K对比横评
  7. 大学计算机aoa学什么,浙江省高校计算机二级AOA考试excel试题及解析.xls
  8. c#生成Excel饼图、柱状图
  9. 领域驱动架构(DDD)建模中的模型到底是什么?
  10. 关于浏览器播放视频的些许理解
  11. 嵌入式软件工程师岗位要求
  12. Mathorcup数学建模竞赛第五届-【妈妈杯】A题:城市相邻两交叉口信号配时优化(附一等奖获奖论文和matlab代码实现)
  13. 微信公众号的Api 一些说明 关于 WeixinJSBridge API
  14. 9月赠书活动名单公布啦!
  15. 【算法百题之四十】整数转罗马数字
  16. Windows 8.1核心版通过注册表启用Guest账号的局域网共享
  17. Java面向对象 继承,super,方法重写
  18. 超透镜案例仿真(5)——宽带消色差 超构透镜模型 补偿相位与几何相位结合 FDTD仿真 超表面
  19. 雷达图文字被遮住的解决办法
  20. java简单atm_Java实现简单银行ATM功能

热门文章

  1. QUESTION: 由于文件 无法被用户‘_apt‘访问,已脱离沙盒并提权为根用户来进行下载。 - pkgAcquire::Run (13: 权限不够)
  2. Android进阶宝典—App响应时间优化
  3. Oracle 递归查询SQL
  4. 珞珈-B生所学 跟学笔记 PPT(一)
  5. Atmel 官方网站中文版
  6. mate9 android os,华为Mate9评测:全新EMUI 5系统 永不卡顿的安卓机?
  7. k8s cpu 和内存资源说明
  8. mysql 开启 thread pool_MySQL線程池(THREAD POOL)的處理
  9. java if或_java中if条件语句里条件的并列
  10. 多核cpu的缓存一致性