目录
一、概述:异常是指程序运行过程中出现的不可预估的错误,异常将导致程序的运行不安找预期结果进行执行
7.1 说明:子类中的重写方法声明的异常类型必须不能大于父类中被重写方法中声明的异常类型
一、概述:异常是指程序运行过程中出现的不可预估的错误,异常将导致程序的运行不安找预期结果进行执行
int a = 10;
int b = 0;
System.out.println(a/b);
//这里运行之后就会出现运行时异常(非受检异常)
//java.lang.ArithmeticException: / by zero
二、体系结构
- Throwable:异常的等级类,是所有异常和错误的父类,只有该类或其子类的实例化对象才能背jvm虚拟机捕获或者被throw进行抛出。也只有该类或其子类的实例才能被catch语句捕获
- Error:表示程序无法捕获的严重错误。如:堆站溢出等
public class ErrorDemo01 { public static void main(String[] args) { print(); } //调用方法后会产生StackOverflowError private static void print(){ print(); } } //这里会造成死循环,最终导致栈堆内存“爆炸”
- Exception:表示程序运行异常,Exception类的异常是可以被捕获的,同时也希望被捕获,否则将影响到程序的正常执行
public static void main(String[] args) { int[] arr = new int[3]; //程序运行后会出现异常,异常内容为:java.lang.ArrayIndexOutOfBoundsException //异常原因为:超出数组的最大下标(数组的下标越界) arr[10] =100; System.out.println(arr[10]); }
三、Exception分类
- 运行时异常(非受检异常)
- 运行时异常编译器不要求必须进行捕获,这类异常一般时因为逻辑错误所产生的
- 因为这类错误比较普遍,如果全部进行捕获肯会导致程序性能的下降
- RuntimeException及其子类都属于运行时异常
- 编译时异常(受检异常)
- 编译时异常在编码阶段就需要程序员进行处理,这类异常一般后果相对比较严重
public static void main(String[] args) { File file = new File("e:\\1.txt"); try { //无论是否产生错误,都必须先对异常进行处理 //这类异常就是受检异常(编译时异常) FileInputStream is = new FileInputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } }
- 编译时异常在编码阶段就需要程序员进行处理,这类异常一般后果相对比较严重
-
语法结构
try{ [代码段] } catch(异常类型 异常对象){ [处理异常] } finally{ [资源释放] }
- 语句的执行
try{ //程序代码从try语句开始进行执行(try一定会被执行) System.out.println("try语句被执行了.............."); int i = 20/0; //异常之后的代码不会被执行 System.out.println("异常之后的语句。。。。。。。。。。"); } catch(Exception e){ //catch语句负责捕获异常 //只有当有异常产生时,才会执行该语句 System.out.println("catch语句被执行了................."); } finally{ //finally语句负责执行资源释放 //无论是否产生异常,资源释放语句都会被执行 System.out.println("finally语句被执行了................"); }
- 执行过程
过程描述:
- 语句从try语句开始进行执行,当try代码段中产生异常时,语句将转去执行catch代码块
- catch主要负责处理异常,只有当try语句段中产生异常时catch语句段才会被执行
- finally语句负责执行资源释放,无论是否产生异常,finally语句都会被执行
注意点:
- try、catch语句中可以有return语句,当遇到return语句时,先跳转执行finally语句,finally语句执行结束后回到return语句进行返回
- try语句必须和catch、finally进行连用,也可以同时使用。但不能独立使用(目前只能关闭jvm才能防止finally语句的执行)
-
try{ System.exit(0); }finally{ System.out.print("ssssssssss"); }
四、解决异常(捕获异常,抛出异常)
Java中的异常是”抓抛式”。当执行引擎对程序代码进行执行时,代码遇到问题且没有进行处理。则生成一个异常对象并抛出给Java运行时系统
4.1 捕获异常 上面(三、3,4,5)
4.2 抛出异常
public static void main(String[] args) throws Exception{
a();
}
public static void a() throws Exception{
b();
}
public static void b() throws Exception{
c();
}
public static void c() throws Exception,RuntimeException, ECMAException {
/*
thorws和thorw的区别:
1.throw抛出的是具体的异常对象,thorws抛出的可能是出现异常的类型
2.throw出现在方法体里,thorws出现在方法签名中
*/
Exception exception = new RuntimeException("手动创建异常对象");
throw exception;
}
- 执行器遇到异常时,如果未对异常进行处理,则将异常向上进行抛出(抛给调用者)
- 调用代码如果仍未对异常进行处理,则继续向上进行抛出。直到最后一级调用(main()方法)
- 如果main()方法中仍无处理代码,则将异常交给系统进行处理
4.3 异常对象的产生
- 自动生成:Jvm虚拟机执行代码遇到异常时将自动创建一个异常对象并进行抛出
- 手动创建:Java中允许以new的方式手动创建异常对象,然后通过throw语句向上进行抛出(抛给方法的调用者)
public static void main(String[] args) throws Exception { a(); } //方法a,他将调用方法c private static void a() throws Exception { c(); } private static void c() throws Exception { //手动实例化一个异常对象,然后通过语句进行抛出 Exception ex = new RuntimeException("这是自定义异常"); throw ex; }
五、 throw与throws
5.1 throw
- 作用:显示将一个异常对象向上进行抛出,抛给方法的调用者
- 语法:throw 异常对象
- 场景:
- 消息超出方法的返回值范围
public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }
-
返回值的内容与方法的返回值类型不一致
private static void checkBounds(byte[] bytes, int offset, int length) { if (length < 0) throw new StringIndexOutOfBoundsException(length); if (offset < 0) throw new StringIndexOutOfBoundsException(offset); if (offset > bytes.length - length) throw new StringIndexOutOfBoundsException(offset + length); }
- 消息超出方法的返回值范围
5.2 throws
- 作用:用于说明方法执行后可能会产生的异常。可以是一个异常列表。
- 场景
- 方法中不知道该如何对异常进行处理,可以通过throws在方法的后面声明可能产生的异常的类型
- throws后可以使用具体的异常类型,也可以是异常的父类型
5.3 简述throw和throws的区别?
- throw出现在方法体内;throws出现在方法签名中
- throw用于向上抛出一个异常对象;而throws用于声明可能会出现的异常的类型
5.4 常见的异常类型
- ClassNotFoundException:类未被发现(依赖未添加)
- EofException:读取到文件末尾
- FileNotFoundException:文件未被发现
- ParseException:类型转换错误
六、自定义异常
概述:在自定义框架或系统中需要用到特定的异常类型,则可以通过继承的方式来扩展异常类型。
实现方式:
[修饰符] class 类型名 extends 异常类型{
[相关代码]
}
6.1 Exception的成员
- 构造器
- Exception():实例化一个异常对象
- Exception(String):实例化一个异常对象并指定消息内容
- 常用方法
- getMessage():返回异常的消息内容
- printStackTrace():将异常消息内容输出到标准输出流
- 自定义异常类
/** * 自定义异常类 * 步骤: * 1、创建类并继成于指定的异常类型(通常情况下继成于RunTimeException) * 2、实现异常类的构造函数 * 3、使用自定义异常类 * @author TerryLiu */ public class MyException extends RuntimeException{ public MyException() { } public MyException(String message) { super(message); } } public class Test { public static void main(String[] args) { method01(2,0); } /** * 使用自定义异常 */ private static int method01(int i,int j) { //判断参数j是否为0,如果是0则抛出一个异常 if(j==0) throw new MyException("参数j不能为0"); if(i==j) throw new MyException("i和j的值不能相对"); return i-j; } }
七、异常与方法重写
【父类】
/**
* @author TerryLiu
*/
public class OverideDemo01 {
/**
* 声明异常的类型为IOException
* @throws IOError
*/
public void say() throws IOException {}
}
【子类】
/**
* 继承OverideDemo01
*/
class Child extends OverideDemo01{
@Override
public void say() throws FileNotFoundException {
}
}
7.1 说明:子类中的重写方法声明的异常类型必须不能大于父类中被重写方法中声明的异常类型
八、final、finally及finalize()的区别
- final:修饰符,用于修饰类、方法、字段及参数。表示不可变的。
- finally:子句,异常处理中用于进行资源释放
- finalize():方法,调用后将调用GC进行垃圾回收
九、使用建议
- try语句段中只定义可能会出现异常的代码,大的try代码段可能会导致程序性能的下降(try中只放可能产生异常的代码)
- catch后尽量使用详细的异常类型(效率会有所提高)
- 当有多个catch语句块时,大的异常类型放在小异常类型的后面
- 语句块中最多只能有一个try、finally,但可以有多个catch
十、意义
- 提高了程序的健壮性
- 用户的提示更加友好