Chapter12 异常Exception
Chapter12 异常Exception
基本介绍
对异常进行捕获,保证程序可以继续运行
快捷键 ctrl + alt + t ===== try-catch
java语言中,将程序执行中发生不正常的情况称为“异常”,(开发过程中的语法错误和逻辑错误不是异常)
执行过程中的所发生的异常事件可分为两大类:
- Error(错误):java虚拟机无法解决的严重问题。比如:JVM系统内部错误,资源耗尽等严重情况。比如StackOverflowError【栈溢出】和OOM(out of memory),error是严重错误,程序会崩溃
- Exception:其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如 空指针访问,试图读取不存在的文件,网络连接中断等等,Exception分为两大类:运行时异常【程序运行时,发生的异常】 编译时异常【编程时,编译器检查出的异常】
异常体系图
Throwable下两个子类 Error和Exception
运行时异常和编译异常
- 运行时异常,编译器检查不出来。一般时编译时的逻辑错误,是程序员应该避免出现的异常。RuntimeErrorException类及他的子类都是运行时异常,对于运行时异常可以不做处理,因为这类异常很普遍,如果完全处理会对程序的可读性和运行效率产生影响
- 编译时异常,是编译器要求必须处理的异常
运行异常
常见运行时异常
NullPointerException 空指针异常 如果一个对象指向了null 但是程序却使用该对象会抛出该异常
ArithmeticException 数学运算异常 整数除以0 出现异常的运算条件时,抛出该异常
ArrayIndexOutOfBoundsException 数组下标越界异常 使用非法的索引访问数组
ClassCastException 类型转换异常 试图将对象强制转换为不是实例的子类,抛出该异常
NumberFormatException 数字格式不正确异常 试图将字符串转换为数字,但该字符串不具备数字意义时候抛出该异常
编译异常
介绍
编译异常是指在编译阶段,就必须处理的异常,否则代码不能通过编译
常见编译异常
SQLException 操作数据库时,查询便可能发生异常
IOException 操作文件时发生的异常
FileNotFoundException 操作一个不存在的文件
ClassNotFoundException 加载类,而该类不存在时,异常
EOFException 操纵文件到文件末尾,发生异常
IIIegalArguementException 参数异常
异常处理
基本介绍
异常处理就是当异常发生时,对异常处理的方式
异常处理的方式
- try-catch-finally 程序员在代码中捕获发生的异常,自行处理
- throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM
try{
代码可能有异常
}catch(Exception e){
捕获异常
当异常发生时,系统将异常封装程Exception对象e,传递给catch
得到异常对象后,程序员自己处理
如果没有异常发生,catch代码块不执行
}finally{
不管try代码块是否有异常发生,始终执行finally
所以,通常释放资源的代码,放在finally中
}
try-catch 异常处理
try包含可能出现异常的代码,catch用于处理try中出现的异常。可以根据需求有多个catch,如果没有finall,语法也是可以通过的
注意事项
package javabase.chapter12;
public class TryCatchDetail {
public static void main(String[] args) {
/**
* 1。 如果异常发生了,则异常后边的代码不会执行,直接进入catch代码块
* 2. 如果异常没有发生,则会顺序执行try的代码快,不会进入catch
* 3. 如果希望不管是否发生异常,都会执行某i段代码(比如关闭连接,释放资源)则使用finally*/
try {
String str = "hahah";
int a = Integer.parseInt(str);
System.out.println("数字"+a);
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
System.out.println(e.getMessage());
System.out.println(e.getMessage());
}
finally {
System.out.println("finally执行");
}
System.out.println("后续代码");
}
}
可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如Exception在后,NoPointException在前
package javabase.chapter12;
public class TryCatchDetail02 {
public static void main(String[] args) {
// 如果try代码块可能有多个异常
//使用多个catch分别捕获不同的异常,相应处理
// 要求 子类异常写在前面 父类异常写在后面(否则编译器会报错,该异常已经被捕获)
try {
Person per = new Person("haha");
per = null;
System.out.println(per.getName());
// }
// catch (NullPointerException e){
// System.out.println(e.getMessage());
// System.out.println("haha");
} catch(Exception e) {
System.out.println(e.getMessage());
System.out.println("heiehi");
}
}
}
class Person{
private String name = "jack";
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
可以进行 try-finally 配合使用, 这种用法相当于没有捕获异常,
因此程序会直接崩掉/退出。应用场景,就是执行一段代码,不管是否发生异常, 都必须执行某个业务逻辑
package javabase.chapter12;
public class TryCatchExercise03 {
public static void main(String[] args) {
System.out.println(method());
}
public static int method(){
int i = 1;
try {
i++;
String[] names = new String[3];
if (names[1].equals("tom")){
System.out.println(names[1]);
}else{
names[3] = "haha";
}
return 1;
}catch (ArrayIndexOutOfBoundsException e){
return 2;
}catch (NullPointerException e){
return ++i;
}finally {
++i;
System.out.println(i);
}
}
}
try-catch-finally 小结
- 如果没有出现异常,则执行try块中的所有语句,不执行catch块中的语句,如果有finally,最后还要执行finally里面的语句
- 如果出现异常,则try中的语句异常发生后,try块剩余的语句不再执行。将执行catch块中的语句,如果有finally最后还需要执行finally中的语句
课后练习
如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止
package javabase.chapter12;
import java.util.Scanner;
public class TryCatchExcerise04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while(true){
System.out.println("请输入整数");
inputStr = scanner.next();
try{
num = Integer.parseInt(inputStr);
break;
}catch (NumberFormatException e){
System.out.println("你输入的不是一个整数");
}
}
System.out.println("num=" + num);
}
}
Throws异常处理
基本介绍
如果一个方法(中的语句执行时)可能生成某种异常,但是并不能准确如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法调用者负责处理
在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是他的父类
快速入门案例
public static void readFile(String file) throws FileNotFoundException{
//读取文件的操作可能会产生FileNotFoundException
FileInputStream fils = new FileInputStream("d://aa.txt");
}
注意事项和使用细节
- 对于编译异常,程序中必须处理,比如 try-catch或者throws
- 对于运行时异常,程序如果没有处理,默认就是throws的方式处理
- 子类重写父类的方法时,对抛出异常的规定:子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
- throws过程中,如果有方法try-catch 就相当于处理异常,就不必throws
package javabase.chapter12;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ThrowsDetail {
public static void main(String[] args) {
}
public static void f2(){
//1.对于编译异常,程序中必须处理,比如 try-catch 或者 throws
//2.对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理
int n1 = 10;
int n2 = 0;
double res = n1/n2;
}
public static void f1() /*throws FileNotFoundException*/{
//说明:调用f3 此时该方法抛出一个编译异常,但是f1方法未处理该异常,所以会报错
//这时需要添加throws 继续抛出该异常 或者用try-catch处理
try {
f3();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void f3() throws FileNotFoundException{
FileInputStream fis = new FileInputStream("d://a.txt");
}
public static void f4(){
//说明:f4这个方法调用f5 为什么不报错
//因为f5抛出的是运行时异常 默认会使用throws处理
//也就是说 f4会抛出这个异常 采用默认的方是 throws
f5();
}
public static void f5() throws ArithmeticException{
}
}
class Father {
public void method() throws RuntimeException{
}
public void method2() throws FileNotFoundException{
}
}
class Son extends Father{
//子类重写父类方法的时候,对于抛出异常的规定:
//子类重写的方法,抛出的异常类型 要么和父类异常类型一致,要么就是父类异常类型的子类
@Override
public void method() throws ArithmeticException {
super.method();
}
@Override
public void method2() {
//重写也可以使用try-catch捕获 做处理 否则会报错
// 如果是运行时异常 重写的时候可以不处理异常
//因为子类会默认调用throws去处理异常
try {
super.method2();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
自定义异常
基本介绍
当程序出现某些”错误“,但该错误信息并没有在Throwable子类中描述处理,这个时候就可以自己设计异常类,用于描述该错误信息
步骤
- 定义类:自定义异常类名(自己写)继承Exception或者RuntimeException
- 如果继承Exception,属于编译时异常
- 如果继承RuntimeException 属于运行时异常,(一般来说,继承RuntimeException)
自定义异常的应用实例
当我们接受Person对象的年龄时,要求范围在18-120之间,否则抛出一个自定义异常(要求:继承RuntimeException),并给出信息提示
package javabase.chapter12;
public class CustomException {
public static void main(String[] args) {
int age = 100;
//要求范围在18-120 否则抛出异常
if (!(age >= 18 && age <= 120)){
//这里我们通过构造器,设置信息
throw new AgeException("年龄需要在18-120");
}
System.out.println("年龄范围正确");
}
}
//说明:
//定义一个异常类
//1.一般情况下,我们自定义异常是继承RuntimeException
//2.即把自定义异常做成 运行时异常 好处是,我们可以使用默认异常处理机制 比较方便
class AgeException extends RuntimeException{
/**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
//构造器
public AgeException(String message) {
super(message);
}
}
throw 和 throws的区别
- throws 异常处理的一种方式 在方法声明处使用 后面跟异常类型
- throw 手动生成异常对象的关键字 在方法体中使用 后面跟异常对象
浙公网安备 33010602011771号