第四阶段 IO

异常处理

没有完美的程序,所以我们需要不断地完善,考虑各种可能性,我们要将除了自己以外的任何用户或者操作者都当成傻子来考虑问题

在我们开发过程中 我们运行时常常会遇到 这样java.lang.XxxException的信息,这代表程序发生了一些错误,也叫作异常

(一) 概述及体系

(1) 概述

异常情形是指阻止当前方法或者作用域继续执行的问题 ——《Think in Java》

简单概括:程序出现不正常情况后,程序将会跳出当前环境,并且抛出异常。

(2) 体系

(1) Error —— 错误:程序无法处理的严重错误,我们不作处理

  • 这种错误一般来说与操作者无关,并且开发者与应用程序没有能力去解决这一问题,通常情况下,JVM会做出终止线程的动作

(2) Exception —— 异常:异常可以分为运行时异常和编译期异常

  • RuntimeException:即运行时异常,我们必须修正代码

    • 这些异常通常是由于一些逻辑错误产生的

      这类异常在代码编写的时候不会被编译器所检测出来,是可以不需要被捕获,但是程序员 也可以根据需要行捕获抛出,(不受检查异常)这类异常通常是可以被程序员避免的。

      常见的RUNtimeException有:NullpointException(空指针异常),ClassCastException (类型转 换异常),IndexOutOfBoundsException(数组越界异常)等。

  • 非RuntimeException编译期异常,必须处理,否则程序编译无法通过

    • 这类异常在编译时编译器会提示需要捕获,如果不进行捕获则编译错误。
    • 常见编译异常有:IOException(流传输异常),SQLException(数据库操作异常)等。

Java内置异常类

A:Java 的非检查性异常

异常 描述
ArithmeticException 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ClassCastException 抛出表示代码尝试将对象转换为不属于实例的子类。 例如:将Integer型对象转换为String类
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
NumberFormatException 抛出以表示应用程序已尝试将字符串转换为其中一个数字类型,但该字符串不具有相应的格式。
IllegalStateException 表示在非法或不适当的时间调用了一种方法。 换句话说,Java环境或Java应用程序对于请求的操作并不处于适当的状态。
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 应用程序可以将此类子类化以指示类似的异常。
ArrayIndexOutOfBoundsException 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
NoSuchElementException 被各种访问器方法抛出,表示被请求的元素不存在。
InputMismatchException 输入类型不匹配异常,一般出现此类异常的原因就是定义的接受输入值的变量的类型与输入的数值的类型不匹配导致的异常。
NullPointerException 空指针异常

B:Java的检查性异常

异常 描述
ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
InstantiationException 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。

(二) 异常处理语句

(1) try-catch

A:捕获单个异常

try{
//程序代码
}catch (ExceptionName e1){
//Catch块
}

B:多重捕获块

try{
//程序代码
}catch (异常类型1 异常的变量名1){
......
}catch (异常类型2 异常的变量名2){
......
}catch (异常类型3 异常的变量名3){
......
}

try:用于监听异常

catch:用于捕获处理异常

try 后面的一对大括号内的内容即受到监控的程序,也就是说这一段代码是可能存在异常的,而Catch中由开发者,根据自身推断可能存在的异常,书写对应异常类型以及处理方式,当程序发生异常时,会创建异常对象,并且将异常抛出到此环境外,Java运行时系统会寻找与发生异常所匹配的catch子句,当找到一个对应语句后则不再寻找其他catch块

public class Demo {
public static void main(String[] args) {
int a = 520;
int b = 0;
int c; try {
System.out.println("这是一个被除数为0的式子");
c = a / b;
} catch (ArithmeticException e) {
System.out.println("除数不能为0");
}
}
} //运行结果
这是一个被除数为0的式子
除数不能为0

通过上例可以看到,被监控的语句中先依次正常执行,当遇到存在问题的语句时,找到匹配异常,并且执行catch块中的语句

而一般来说我们会在catch语句块中通过异常对象执行异常方法

方法方法 说明
public String getMessage() 回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了
public Throwable getCause() 返回一个Throwable 对象代表异常原因
public String toString() 使用getMessage()的结果返回类的串级名字
public void printStackTrace() 打印toString()结果和栈层次到System.err,即错误输出流

我们还是用上面的例子给出异常方法的测试

System.out.println(e.getMessage());

/ by zero
System.out.println(e.getCause());

null
System.out.println(e.toString());

java.lang.ArithmeticException: / by zero
e.printStackTrace();

java.lang.ArithmeticException: / by zero
at cn.bwh_01_Throwable.Demo.main(Demo.java:10)

(2) try-catch-finally

我们在 try-catch的基础上再补充一个finally的知识

finally 关键字用来创建在 try 代码块后面执行的代码块无论是否发生异常,finally 代码块中的代码总会被执行,在 finally 代码块中,可以运行清理类型等收尾善后性质的语句,finally 代码块出现在 catch 代码块最后,语法如下:

try{
......
}catch(异常类型1 异常的变量名1){
......
}catch(异常类型2 异常的变量名2){
......
}finally{
......
}

无论是否发生异常,fianlly始终都是会运行的

这里就不得不提一个非常重要的注意点,那就是当return遇到finally

注意点

A:return遇到finally

我们来看下面一个例程:

public class Demo2 {
public static void main(String[] args) {
System.out.println(test());
} public static String test(){
int[] array = new int[2];
try{
array[3] = 0;
return "This is try";
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
return "This is catch 1";
}catch (Exception e){
System.out.println(e);
return "This is catch 2";
}finally {
System.out.println("This is finally");
//return "This is finally's return";
}
}
} //运行结果
java.lang.ArrayIndexOutOfBoundsException: 3
This is finally
This is catch 1

由此我们得出一个结论:在catch中遇到return时,仍然会先执行finally语句,再回来执行对应catch语句中的return语句

但是我们如果将finally中return行中的注释去掉,运行结果就会变成下面这样子

//运行结果
java.lang.ArrayIndexOutOfBoundsException: 3
This is finally
This is finally's return

结果就是返回值会被finally中的return语句重新覆盖

B:catch 顺序问题
public class Demo3 {
public static void main(String[] args) {
int[] array = new int[2];
try{
array[5] = 0;
}catch (Exception e){ }catch (ArrayIndexOutOfBoundsException e){ }
}
} //运行结果
Error:(8, 10) java: 已捕获到异常错误java.lang.ArrayIndexOutOfBoundsException

对于多个catch的情况,当try中程序发生异常,会按照从上往下的顺序与catch进行匹配,一旦与其中一个匹配后就不会再与后面的catch进行匹配了,所以,在书写catch语句的时候,一定要把范围小的放在前面,范围大的放在后面!

(3) throw/throws

将自己处理不了的,在方法或者语句上声明,告诉调用者,这里有问题

如果一个方法没有捕获到检查性异常,那么该方法就必须使用throws关键字声明(声明抛出多个异常,之间使用逗号隔开),也可以在语句中使用throw关键字抛出一个异常。

//演示throw
public class Demo4 {
public static void main(String[] args) {
test();
} public static void test() {
int a = 520;
int b = 0;
if (b == 0) {
throw new ArithmeticException();
} else {
System.out.println(a / b);
}
}
} //运行结果
Exception in thread "main" java.lang.ArithmeticException
//演示throws

public class Demo4 {
public static void main(String[] args) {
try {
test();
} catch (Exception e) {
e.printStackTrace();
}
} public static void test() throws Exception {
int a = 520;
int b = 0;
if (b == 0) {
throw new Exception();
} else {
System.out.println(a / b);
}
}
} //运行结果
java.lang.Exception
throws和throw的区别

A:throws

  • 用在方法声明后,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,不一定会发生这些异常

B:throw

  • 用在方法体内,跟的是异常对象名

  • 只能抛出一个异常对象名

  • 表示抛出异常,由方法体内的语句处理

  • 执行throw则一定抛出了某种异常

(三) 自定义异常

Java内置的异常类,基本可以满足我们在编程中遇到的大部分异常情况,此外我们还可以自定义异常类,只需要继承Exception类即可

基本步骤:

  • 创建自定义异常类

  • 在方法中通过throw抛出异常对象

    • 在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获处理
    • 也可以在方法声明处使用throws将异常抛给方法调用者
  • 在出现异常方法的调用者中捕获并且处理异常

class MyException extends Exception {  // 自定义的类
MyException(String s) {
super(s);
}
}
class Demo {
void method() throws MyException {
throw new MyException("Wrong"); // 抛出自定义的类
}
}
class DemoTest {
public static void main(String[] args){
try {
new Demo().method();
}
catch(MyException e) {
System.out.println(e.getMessage());
}
}
} //运行结果
Wrong

(三) 总结

异常就是在程序发生异常时,强制终止程序运行,并且将异常信息返回,由开发者决定是否处理异常

简单说一下这个异常机制的过程:

当程序无法运行后,它会从当前环境中跳出,并且抛出异常,之后,它会先new一个异常对象,然后在异常位置终止程序,并且将异常对象的引用从当前环境中返回,这时候异常处理机制接管程序,并且开始寻找可以继续执行程序的恰当位置。

结尾:

如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !_

如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)

在这里的我们素不相识,却都在为了自己的梦而努力 ❤

一个坚持推送原创Java技术的公众号:理想二旬不止

究竟什么是Java异常?的更多相关文章

  1. 全面理解java异常机制

    在理想状态下,程序会按照我们预想的步骤一步一步的执行,但是即使你是大V,你也不可避免出错,所以java为我们提供了异常机制.本文将会从以下几个方面介绍java中的异常机制: 异常机制的层次结构 异常的 ...

  2. 讲解java异常

    J2EE项目异常处理                        为什么要在J2EE项目中谈异常处理呢?可能许多java初学者都想说:“异常处理不就是try….catch…finally吗?这谁都会 ...

  3. 这样设计 Java 异常更优雅,赶紧学!

    来源:lrwinx.github.io/2016/04/28/如何优雅的设计java异常/ 导语 异常处理是程序开发中必不可少操作之一,但如何正确优雅的对异常进行处理确是一门学问,笔者根据自己的开发经 ...

  4. 这样设计 Java 异常更优雅

    转自:lrwinx.github.io/2016/04/28/如何优雅的设计java异常/ 导语 异常处理是程序开发中必不可少操作之一,但如何正确优雅的对异常进行处理确是一门学问,笔者根据自己的开发经 ...

  5. 浅谈java异常[Exception]

    学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:589809992 我们一起学Java! 一. 异常的定义 在<java编程思想 ...

  6. 基础知识《十》java 异常捕捉 ( try catch finally ) 你真的掌握了吗?

    本文转载自  java 异常捕捉 ( try catch finally ) 你真的掌握了吗? 前言:java 中的异常处理机制你真的理解了吗?掌握了吗?catch 体里遇到 return 是怎么处理 ...

  7. Java异常体系及分类

    上图是基本的java异常体系结构. 主要分为2大类:Error和Exception 1.Error:描述了Java运行系统中的内部错误以及资源耗尽的情形.应用程序不应该抛出这种类型的对象,一般是由虚拟 ...

  8. Java异常之自定义异常

    哎呀,妈呀,又出异常了!俗话说:"代码虐我千百遍,我待代码如初恋". 小Alan最近一直在忙着工作,已经很久没有写写东西来加深自己的理解了,今天来跟大家聊聊Java异常.Java异 ...

  9. 第11章 Java异常与异常处理

    1.Java异常简介 1.什么是异常异常出现的时候代码会无法正常运行下去,会产生各种问题2.捕捉异常的作用提早发现异常,方便查找问题,并给出解决方法3.Java中的异常1.Java中所有不正常的类都是 ...

随机推荐

  1. PHP mysqli_connect_errno() 函数

    返回上一次连接错误的错误代码: <?php $con=mysqli_connect("localhost","wrong_user","my_p ...

  2. IDEA更改Maven项目的webapp的版本号

    使用Maven新建的web项目后默认的web.xml为2.3的,以前每次都是从其他文件中拷贝过来的2.5或者3.1的进行替换,怎样指定默认创建web项目的版本? 1.使用IDEA的Help文档具体的过 ...

  3. SQL Server Report Server

    1.SQL Server Report Server是利用mircosoft的share point产品 在menu 打开Reporting Services Configuration进行配置,会自 ...

  4. rxjs入门指南

    使用场景 在复杂的,频繁的异步请求场景,使用rxjs. 在依赖的多个异步数据,决定渲染的情景,使用rxjs. 总之:在前台频繁的.大量的.和后台数据交互的复杂项目里面,使用rxjs(web端,iOS, ...

  5. scrapy框架之Pipeline管道类

    Item Pipeline简介 Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清洗.验证和存储数据.当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数 ...

  6. keepalived+mysql双主热备

    这里使用keepalived实现mysql的双主热备高可用 实验环境: 主机名 IP 系统版本 软件版本 master 192.168.199.6/vip:192.168.199.111 Rhel7. ...

  7. 在AspNetCore3.0中使用Autofac

    1. 引入Nuget包 Autofac Autofac.Extensions.DependencyInjection 2. 修改Program.cs 将默认ServiceProviderFactory ...

  8. 使用linux中,最让人无语的是软件源

    使用linux的最大的障碍是软件源的配置和系统的安装,这两个搞定了,坚持使用下去都不是问题,如果实在不行,还可以win10下的linux子系统可以作为基本的使用.下面记录两个软件源: Found 2 ...

  9. Redis集群都有哪些模式

    前言: 一,为什么要使用redis 1,解决应用服务器的cpu和内存压力 2,减少io的读操作,减轻io的压力 3,关系型数据库扩展性不强,难以改变表的结构 二,优点 1,nosql数据库没有关联关系 ...

  10. 总结:Apache/Tomcat/JBOSS/Jetty/Nginx区别 .

    总结:Apache/Tomcat/JBOSS/Nginx区别 .1.Apache是Web服务器,Tomcat是应用(Java)服务器.Tomcat在中小型系统和并发访问用户不是很多的场合下被普遍使用. ...