Java异常
1.基本介绍
1.Java语言中,将程序执行中发生的不支持情况称为异常。(开发过程中的语法错误和逻辑错误不是异常)。
2.异常分为两类:
①Error(错误):Java虚拟机无法解决的严重问题。如:JVM系统内部错误,资源耗尽等严重情况。比如:栈溢出,内存溢出,Error是严重错误,程序会崩溃。
②Exception:其他因编程错误或偶然因素导致的一般性问题,可以使针对性的代码进行处理。例如空指针访问,试图读取不存在文件等等,Exception分为两大类。运行时异常和编译时异常。
2.异常体系图
常见的异常体系图
运行时异常和编译时异常发生时间:
总结:
运行时异常,编译器不要求强制处理的异常,一般是编程是的逻辑错误,是应该避免出现的异常。同时编译器检查不出来运行时异常。
对于运行时异常,可以不做处理,因为这类异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响。
编译时异常,是编译器要求必须处理的异常。
3.常见的运行时异常
(1)NullPointerException:空指针异常
当程序需要在使用对象,但是值为null时,抛出该异常。代码和运行图如下:
public class NullPointerException_ {
public static void main(String[] args) {
String str = null;
System.out.println(str.length());
}
}
图片:
(2)ArithmeticException:数学运算异常
当出现异常运算时,抛出此异常,例如一个整数,除以0时,抛出异常。代码和运行图如下:
public class ArithmeticException_ {
public static void main(String[] args) {
int num1 = 10, num2 = 0;
System.out.println(num1 / num2);
}
}
图片:
(3)ArrayIndexOutOfBoundsException:越界异常
用非法的索引访问数组时抛出的异常,如果索引为负或者大于等于数组大小,则该索引为非法索引,代码和运行图如下:
public class ArrayIndexOutOfBoundsException_ {
public static void main(String[] args) {
int[] arr = new int[4];
System.out.println(arr[4]);
}
}
图片:
(4)ClassCastException:类型转换异常
当试图将对象强制转换不能进行时,抛出该异常。代码和运行图如下:
public class ClassCastException_ {
public static void main(String[] args) {
A b = new B(); // 多态, 向上转型
B b1 = (B) b; // 多态, 向下转型
C c = (C) b; // 报错
}
}
class A {
}
class B extends A {
}
class C extends A {
}
图片:
(5)NumberFormatException
当程序试图转换字符串变为一种数值类型,但是不能转换时,抛出该异常。代码和运行图如下:
public class NumberFormatException_ {
public static void main(String[] args) {
String str = "hh6879";
Integer.parseInt(str);
}
}
图片:
4.常见的编译时异常
1.基本介绍
编译异常是指编译期间,就必须处理的异常,否则代码不能通过编译。只做了解即可。
2.常见编译异常
①SQLException:操作数据库,查询表发生的异常。
②IOException:操作文件时,发生的异常。
③FileNotFoundException:当操作一个不存在的的文件发生异常。
④ClassNotFoundException:加载类,而该类不存在异常。
⑤EOFException:操作文件,到文件末尾,发生异常。
⑥IllegalArguementException:参数异常。
5.异常处理
1. 基本介绍
①异常处理就是当异常发生时,对异常的处理方式。
②1.try-catch-finally
程序员在代码中捕获发生的异常,并自行处理。
②throws
将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者是JVM。
2. 示意图
1.try-catch-finally示意图:
2.throw示意图:
以main方法调用了f1方法而f1方法又调用了f2方法为例
6.try - catch 异常处理。
1.基本介绍
Java提供try和catch块来处理异常,try块用于包含可能含有出错的代码。catch块用于处理try块中发生的异常。可以更具需要在程序中写多个数量的catch块。
2.基本语法
try{
// 可疑代码
// 将异常生成对应的异常对象,传递给catch块
} catch{
// 对异常的处理
// 没有finally,语法也可以通过
3.细节
①在try-catch里如果异常发生,异常发生后的代码不会执行,直接进入catch块中。代码和运行结果图如下:
public class TryCatchDetail {
public static void main(String[] args) {
try {
System.out.println("开始");
int num1 = 1, num2 = 0;
num1 = num1 / num2;
System.out.println("try执行");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
图片:
②如果异常没有执行,则顺序执行try里的代码,不会进入catch中。代码和运行结果图如下:
public class TryCatchDetail {
public static void main(String[] args) {
try {
System.out.println("开始");
int num1 = 1, num2 = 0;
// num1 = num1 / num2;
System.out.println("try执行");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
图片:
③如果不管异常发不发生,都执行某段代码。则使用finally。
public class TryCatchDetail {
public static void main(String[] args) {
try {
System.out.println("开始");
int num1 = 1, num2 = 0;
num1 = num1 / num2;
System.out.println("try执行");
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
System.out.println("finally...执行");
}
}
}
图片:
④,可以有多个catch语句,捕获不同的异常进行不同的业务处理,要求子类异常在前,父类异常在后,比如NullPointerException在前,Exception在后。如果发生异常只会匹配一个catch,代码和运行图如下:
public class TryCatchDetail02 {
public static void main(String[] args) {
try {
String str = null;
System.out.println(str.length());
int num1 = 1, num2 = 0;
num1 = num1 / num2;
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
图片:
⑤也可以try-finally配合使用,这种用法相当于没有捕获异常,因此程序会崩掉。应用场景,就是执行一段代码,不管是否发生异常,都会执行某个逻辑。finally执行完毕,程序中断。代码和运行图如下:
public class TryCatchDetail03 {
public static void main(String[] args) {
try {
int num1 = 10, num2 = 0;
System.out.println(num1 / num2);
} finally {
System.out.println("finally...被执行");
}
System.out.println("程序继续运行");
}
}
图片:
7.throws 异常处理。
1.基本介绍
①如果一个方法中的语句执行时可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显式的声明抛出异常,表示该方法不对这些进行处理,而由该方法的调用者进行处理。
②在方法的声明中使用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是他的父类。
③throws关键字后面也可以是异常列表,即可抛出多个异常。
2.细节
1.对应编译异常,程序中必须处理。用try-catch或者throws。代码如下:
class A{
public void f1() throws Exception{
}
public void f2(){
f1(); // 报错
}
}
2.对于运行时异常,程序可以不处理,默认处理是throws。代码如下:
class A{
public void f1() throws RuntimeException{
}
public void f2(){
f1(); // 没有报错
}
}
3.子类重写父类方法时,对于抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类一致,要么时父类抛出异常的子类。代码如下:
class A {
public void f1() throws RuntimeException {
}
public void f2() {
f1();
}
}
class B extends A {
@Override
public void f1() throws NullPointerException {
}
}
4.在throws过程中,如果有方法和在try-catch相关异常,就相当于处理异常,就可以不throws了。
5.运行时异常默认有throws处理,Java中并不要求程序员显示处理,因为有默认处理机制。
8.自定义异常
1.基本介绍
当程序出现了某些错误,但是该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该信息。
2.步骤
①自定义异常类名(自己定),继承Exception类或者RuntimeException
②如果继承Exception,属于编译异常。
③如果继承RuntimeException,属于运行时异常(一般来说,继承RuntimeException)。好处:我们可以使用默认的处理机制,比较方便。
3.例子演示
名称长度需要在2到10之间,代码和运行图如下:
public class StrException {
public static void main(String[] args) {
String name = "hh68796666666666666666666666666";
if (!(name.length() >= 2 && name.length()<=10)){
throw new StringException("名称长度需要在2到10之间");
}
System.out.println("名称长度正确");
}
}
class StringException extends RuntimeException {
public StringException(String message){
super(message);
}
}
运行图:
4.throws与throw的区别
意义 | 位置 | 后面跟的东西 | |
---|---|---|---|
throws | 异常处理的一种方式 | 方法声明处 | 异常类型 |
throw | 手动生成异常处理对象的关键字 | 方法体中 | 异常对象 |