。
先看文章目录,大致了解知识点结构,直接点击文章目录可以跳转到文章指定位置。
生活中异常举例:异常就是不正常情况,比如汽车运行的时候因为未知原因熄火了,电脑死机了。
在Java中异常 :就是程序出问题了无法得到预期的结果,异常了程序没运行成功。例如:空指针异常、类型转换异常、下标越界异常。
Java异常机制:是 Java 提供的一种识别及响应错误的一致性机制。
①使程序中异常处理代码和业务代码分离。
②异常机制为我们提供了三类信息包括:
1、异常类型信息:什么被抛出
2、异常堆栈跟踪信息:在哪抛出
3、异常信息:为什么会抛出
异常 | 解释 |
---|---|
InputMismatchException | 输入类型不匹配的异常 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 变量不存在 |
NoSuchMethodException | 方法不存在 |
/*
演示异常出现的场景问题:
运行时异常:算数异常
java.lang.ArithmeticException: / by zero
*/
public class TestException {
public static void main(String[] args) {
div(10, 0);
}
//计算两个整数的商
public static void div(int a,int b) {
double num = a / b;
System.out.println("商为:" + num);
}
如图因为除数不能为0所以产生了异常:Exception in thread “main” java.lang.ArithmeticException: / by zero
①自定义编译期异常类需要继承 Exception 类。
②自定义运行时异常类,需要继承 RuntimeException 类。
③异常类同样可以拥有自己的属性和方法。
//自定义异常类
public class MyException extends RuntimeException{
static final long serialVersionUID = -70348971945766939L;
//构造方法
public MyException() {
}
public MyException(String message) {
super(message);
}
}
使用throw 关键字抛出异常,什么是抛出异常呢?
是java中一个程序处理动作。如果一个方法没有使用try…catch捕获可能引发的异常,为了明确指出此方法不捕获这类异常,并且要让调用该方法的其他方法去捕获处理该异常。我们就使用throws明确的抛出(产生)该类异常。
/*
演示手动抛出异常对象=关键字:throw
*/
public class TestException_5 {
public static void main(String[] args) {
People p = new People("张三", 140);
System.out.println(p);
//...
}
}
//------------------------------分割----------------------------
class People{
private String name;
private int age;
public People() { }
public People(String name, int age) {
this.name = name;
//数据合理性的校验
if (age <= 0 || age > 130) {
// System.out.println("年龄不合理..."); //打印信息
// throw new RuntimeException("年龄有误!"); //抛出异常,因为是运行时异常可以处理也可以不处理
// throw new Exception("年龄有误..."); //抛出异常,因为不是运行时异常所以必须处理
throw new MyException("年龄有误...");//抛出异常,因为是运行时异常的子类可以处理也可以不处理
} else {
this.age = age;
}
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
如果异常一直用throw抛出总不是个事情,异常总得有处理的时候这时候需要用到throws和try…catch…finally
ps:idea中添加try-catch的快捷方式:选中代码 -> ctrl + alt + t
①try结构:将可能出现异常的代码定义其中,异常对象出现后,jvm就会调用catch结构尝试捕获处理它。
②catch结构:异常对象出现,jvm会让第一个catch结构尝试捕获处理:,如果类型匹配,则捕获成功,执行catch大括号中的逻辑代码;如果类型不匹配,则捕获失败,则调用下一个catch结构继续尝试捕获…
③try结构中出现了异常对象,被catch结构捕获处理后,try-catch结构内的后续代码不可以被继续执行,try-catch结构以外的后续代码可以继续被执行。
④ 如果多个catch结构涉及的异常类型存在子父类的关系,则类型小的catch必须定义在类型大的catch的上面。
⑤finlly结构,它被定义在最后位置,将一定需要被执行的代码定义在finally的内部,finally中的代码一定会被执行。
案例一: try…catch结构
/*格式: try{
//可能出现异常的代码
}catch(异常类型1 对象名){
//逻辑代码
}catch(异常类型2 对象名){
//逻辑代码
}
*/
public class TestException_3 {
public static void main(String[] args) {
test2();
}
public static void test2() {
/*
运行时异常:数组下标越界异常
java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
*/
try {
int[] arr = new int[10];
System.out.println(arr[10]);
} catch (Exception e) { //参数位置可能发生多态 万能捕获器 表现:Exception e = new ArrayIndexOutOfBoundsException();
e.printStackTrace(); //打印堆栈信息 ==> 将异常对象所属的类型、原因、涉及的行数打印展示在控制台
// System.out.println(e.getMessage()); //得到异常出现的原因
}
System.out.println("执行了");
}
}
案例二: try…catch结构
public class TestException_3 {
public static void main(String[] args) {
test3();
}
public static void test3() {
/*
运行时异常:空指针异常
java.lang.NullPointerException
*/
try {
String str = "javase";
str = null;
int size = str.length();
System.out.println("长度为:" + size);
} catch (NullPointerException e){
System.out.println("出现空指针异常啦!已经处理完毕...");
} catch(Exception e) {
System.out.println("万能捕获器未被触发,因为前面已经触发了空指针异常");
}
System.out.println("可以执行了");
}
}
案例三: try…catch…finally结构中,finlly被定义在最后位置,将一定需要被执行的代码定义在finally的内部,finally中的代码一定会被执行。
/*格式: try{
//可能出现异常的代码
}catch(异常类型1 对象名){
//逻辑代码
}catch(异常类型2 对象名){
//逻辑代码
}finally{
//定义一定需要被执行的代码
}
*/
public class TestException_3 {
public static void main(String[] args) {
test4();
}
public static void test4() {
FileInputStream fis = null;
try {
fis = new FileInputStream("hello2.txt");
int len;
while ((len = fis.read()) != -1) {
System.out.println((char) len);
}
int num = 10 / 0;
} catch (Exception e) {
e.printStackTrace();
}finally { //这里面的代码一定会执行
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("执行了");
}
}
②Java中声明异常(throw exception):一个方法产生了一个它不想立即处理的异常时,那么就需要在该方法的头部使用throws主动声明这个异常,告诉调用者可能出现问题,后面交给外部进行处理,以达到延后处理的目的。
如下代码:m1方法中的异常最终交给了m3方法解决。
/* 关键字:throws 格式:
public ... 返回值类型 方法名(形参列表) throws 异常类型1,异常类型2,...,异常类型n{
//方法体
}
*/
public class TestException_4 {
public static void main(String[] args) {
m3();
}
public static void m3(){
try {
m2();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void m2() throws IOException {
m1();
}
public static void m1() throws IOException {
FileInputStream fis = new FileInputStream("hello.txt");
int len;
while ((len = fis.read()) != -1) {
System.out.println((char) len);
}
fis.close();
}
}
① throw:用来抛出异常的,用于异常对象的产生;
throws:用来声明异常的,用于异常对象的处理;
②通常在一个方法(类)的声明处通过 throws 声明方法(类)可能拋出的异常信息,而在方法(类)内部通过 throw 声明一个具体的异常信息。
③throws 通常不用显示地捕获异常,可由系统自动将所有捕获的异常信息抛给上级方法; throw 则需要用户自己捕获相关的异常,而后再对其进行相关包装,最后将包装后的异常信息抛出。