异常Exception
基本概念
java语言中,把程序执行中发生的不正常情况称为“异常“。(开发过程中的语法错误和逻辑谱误不是异常)
执行过程中所发生的异常事件可分为两大类
- Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资耗尽等严重情况。比如:StackOverflowError[栈溢出]和OOM(out of memory),Error是严重错误程序会崩溃。
- Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常(程序运行时的异常)和编译时异常(编译时,编译器检查出的异常)。
在程序执行的过程中,程序可能出现异常,当程序异常后就崩溃退出来,后面的代码就不再执行。需要程序在执行过程中遇到非致命的问题时继续执行后面的代码则需要一个异常处理机制解决。即:try-catch异常处理。提高代码的健壮性。idea中选中代码(Ctrl+Alt+T),选择try-catch即可。
运行异常
public class Exception01 {
public static void main(String[] args) {
System.out.println("代码开始执行");
int a=1;
int b=0;
try {
int c=a/b;
} catch (Exception e) {
// e.printStackTrace();
System.out.println("提出异常:"+e.getMessage());
}
System.out.printf("继续");
}
}
小结
异常分为两大类:运行时异常和编译时异常。运行时异常,编译器不要求强制处理。通常是指编程时的逻辑错误,是程序员应该避免的异常java.lang.RuntimeException类以及它的子类都是运行时的异常。编译时异常,是编译器要求必须处理的异常。
异常体系统图
体现了继承和实现关系
异常体系统图
运行时异常
NullPointerException空指针异常
当程序试图在需要对象的地方使用了null,抛出的异常
public class NullPointerException_ {
public static void main(String[] args) {
String name= null;
System.out.println(name.length());
}
}
ArithmeticException数字运算异常
出现异常的运算条件时抛出该异常,例如除数为零
public class ArithmeticException_ {
public static void main(String[] args) {
int a=1;
int b=0;
try {
int c=a/b;
} catch (Exception e) {
// e.printStackTrace();
System.out.println(e.getMessage());// 数字运算异常
}
}
}
ArrayIndexOutOfBoundsException下标越界异常
用非法索引访问数组,索引值不在数组大小范围内;抛出该异常。
public class ArrayIndexOutOfBoundsException_ {
public static void main(String[] args) {
int[] arr={1,2,3};
for (int i = 0; i < arr.length+1; i++) {
System.out.println(arr[i]);
}
}
}
ClassCastException类型转换异常
试图把对象强制转换为不是实例的子类抛出该异常。
public class ClassCastException_ {
public static void main(String[] args) {
A b=new B(); // 向上转型
B b2=(B)b; // 向下转型
C c=(C)b; // 类型转换异常
}
}
class A{}
class B extends A{}
class C extends A{}
NumberFormatException数字格式不正确异常
程序试图把字符串转换为数值类型,但是该字符串不能转换时抛出该异常。
public class NumberFormatException_ {
public static void main(String[] args) {
String Str1="123";
String Str2="i1l2k3";
int num =Integer.getInteger(Str1);
int num2 =Integer.getInteger(Str2);
}
}
编译异常
- SQLException操作数据库时,查询表可能发生异常
- IOException操作文件时发生的异常
- FileNotFoundException操作一个不存在的文件时发生的异常。
- ClassNotFoundException加载类,类不存在时发生的异常
- EOFException操作文件,到文件末尾,发生的异常
- IllegalArguementException参数异常
public class Exception01 {
public static void main(String[] args) {
try {
FileInputStream fis;
fis= new FileInputStream("C:\\不存在的图片.png");
int len;
while ((len=fis.read())!=-1){
System.out.println(len);
}
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
异常处理方式
try-catch-finally处理机制示意图
程序员在代码中捕获发生的异常,自行处理
try-catch-finally处理机制示意图
throws处理机制示意图
try-catch-finally和throws二选一处理,若程序员没有显示处理异常,默认throws处理。把发生的异常抛出,交给调用者(方法)处理,最高级处理者为JVM
throws处理机制示意图
try-catch异常处理
- 如果没有异常执行try块中所有语句
- 如果异常发生了,则try异常语句后面的代码不会执行,直接进入catch代码中;如果异常没有发生,则不会执行catch代码块
- 需要无论异常是否发生都执行的代码,使用finally。
- 可以有多个不同的catch语句捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,如果发生异常只会匹配一个catch
public class Try_ {
public static void main(String[] args) {
String str="无法转为数字的字符串";
// String str="1234";
try {
int a=Integer.parseInt(str);
System.out.println("Number:"+str);
} catch (NumberFormatException e) {
System.out.println("异常信息:"+e.getMessage());
}finally {
System.out.println("无论代码是否异常都输出");
}
System.out.println("程序继续运行");
}
}
使用多个catch
public class Try_ {
public static void main(String[] args) {
try {
Person person = new Person();
person = null;
System.out.println(person.getName());// 空指针异常
int n1 = 11;
int n2 = 0;
int n3 = n1 / n2;// 数字运算异常
} catch (NullPointerException e) {
System.out.println("单独捕获空指针异常:" + e.getMessage());
} catch (ArithmeticException e) {
System.out.println("单独捕获算数异常:" + e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
}
}
}
class Person {
private String name = "rick";
public String getName() {
return name;
}
}
可以使用try-finally组合:相当于没有捕获异常,程序会因此崩溃;应用场景:执行一段代码,无论是否发生异常都需要执行的业务逻辑
public class Try_ {
public static void main(String[] args) {
try{
int n1=1;
int n2=0;
System.out.println(n1/n2);
}finally {
System.out.println("程序执行力finally");
}
System.out.println("程序继续执行 ");
}
}
throws异常处理
- 如果一个方法可能发生某种不能确定如何处理的异常,则此方法应现实地抛出异常,表明该方法不对这些异常进行处理,而是由调用者处理。
- throws关键字也可以是异常列表(抛出多个异常)。
- 子类重写父类的方法时,对抛出异常的规定是子类重写的方法所抛出的异常类型和父类一致,或是父类抛出异常类型的子类型。
- 对于异常处理,程序没有处理则默认使用throws方式处理(参考throws处理机制示意图)
- 在throws过程中,如果有try-catch,相当于处理了异常就不必throws
public class Throws_ {
public static void main(String[] args) {
try {
fun1();
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
System.out.println("这是一个throws异常处理的示例");
}
public static void fun1() throws FileNotFoundException {
// 创建一个文件流
FileInputStream fis =new FileInputStream("D://test.txt");// FileNotFoundException编译异常(必须处理)
}
}
自定义异常
程序出现某些错误,但是错误信息不再Throwable子类中描述处理时需要自行设计一个异常处理类
定义类:自己定义异常类名继承Exception或RuntimeException;继承Exception属于编译异常,(通常使用)继承RuntimeException属于运行异常;即把自定义异常做成运行时异常。
public class custom {
public static void main(String[] args) /*throws AgeExcption*/{// 如果定义成编译异常这里还要使用throws AgeExcption
int age=88;
if (age>=18&&age<=140){
// 通过构造器设置信息
throw new AgeExcption("年龄要在正常范围内");
}
System.out.println("你的年龄正常");
}
}
// 自定义异常
class AgeExcption extends RuntimeException/*Exception*/{
public AgeExcption(String msg){ // 构造器
super(msg);
}
}
throws和throw的区别
意义 | 位置 | 后面的内容 | |
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常对象的关键字 | 方法体中 | 异常对象 |
异常流程
public class Exception01 {
public static void main(String[] args) throws Exception {
try {
Test();
System.out.println("A");
} catch (Exception e) {
System.out.println("B");
}finally {
System.out.println("C");
}
System.out.println("D");
}
public static void Test() throws Exception{
throw new Exception();
}
}