异常的概念
程序在运行过程中出现的特殊情况
异常处理的必要性:不对异常进行处理,可能导致程序中断,造成不必要损失
异常的分类
Throwable类
Throwable类:可抛出的,一切错误或异常的父类,位于java.lang包中
public class Throwable
extends Object
implements Serializable
的 Throwable类是java语言中的所有错误和异常的基类。只有这个类的实例对象(或其子类)由java虚拟机或者可以通过java throw语句抛出。
- Error:JVM、硬件、执行逻辑错误,不能手动处理。一个 Error是 指Throwable表明合理的应用程序不应该试图抓住一类严重的问题
- Exception:程序运行/配置出现的问题,可处理。
常见:空指针异常,数组/字符串越界异常,算数异常ArithmeticException
,类型间转换不兼容时引发的运行时异常,数字格式化异常
Exception异常:
- RuntimeException:是可以在java虚拟机正常运行时抛出异常的类,可处理,可不处理
- CheckedException:受查异常,必须处理,不处理无法通过编译
异常的产生
- 自动抛出异常:当程序运行遇到不符合规范的代码和结果时,产生异常
- 手动抛出异常:语法:throw new 异常类型(实际参数)
- 产生异常结果:相当于遇到return语句,导致程序因异常而结束
异常的传递:
按照方法的调用链反向传递,如始终没有处理异常,最终由JVM进行默认处理异常(打印堆栈处理信息)
受查异常:throws 声明异常,修饰在方法参数列表后端
运行时异常:因为可处理可不处理,无需声明异常
异常的处理:
try{
可能出现异常的代码
}catch(Exception e){
异常处理代码
catch(Exception e){
}
}finally{//无论是否出现异常,都需要执行的代码结构,用于释放资源
代码块
}
返回错误内容
String getMessage()
返回该错误的详细信息的字符串。
如果一个 catch 子句要捕获一个类型为 E 的被检查异常, 而其相对应的 try 子句不能抛出 E 的某种子类型的异常,那么这就是一个编译期错误。
多重catch:在一个try块后面捕获不同的异常,遵循从子类到父类顺序的关系(直接继承)
自定义异常:
继承自Exception或Exception的子类,通常为RuntTimeException
必要提供的构造方法:
无参数构造方法
String类型的有参构造方法
class AgeException extands Exception{
}
class SexMisException
class Student implements {
String name;
String sex;
Integer age;
Double score;
public Student() {
super();
}
public Student(String name, Integer age, Double score, String sex) throw AgeException{
super();
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
throw AgeException()//注意方法内抛出的异常不可大于方法外异常范围
}
方法覆盖:
带有异常声明的方法覆盖
- 方法名,参数列表,返回值类型必须和父类相同
- 子类访问修饰符和父类相同或者比父类更宽
- 子类中方法不可抛出比父类更多更宽的异常
import java.util.InputMismatchException;
import java.util.Scanner;
public class ExpectionLearning {
public static void main(String[] args)throws Exception {
System.out.println("Exception");
Students a=new Students();
// a.setAge(290);
a.m1();
a.setAge(70);
System.out.println(a.getAge());
}
}
class Students{
private int age;
public int getAge(){
return age;
}
public void m1()throws Exception{
System.out.println("m1-start");
m2();
Scanner a=new Scanner(System.in);
try {
int b = a.nextInt();
System.out.println(100/b);
}catch(InputMismatchException e){System.out.println("请输入整数");}//多重异常处理,当父类异常在子类关系前被catch,则子类异常不会被catch
catch(ArithmeticException e){System.out.println("输入不可为0");}
catch (Exception E){System.out.println("unknown");}
finally{
System.out.println("m1-end");}
}
public void m2()throws Exception{//当Exception没有被处理时,println("m2-end")不会被执行
System.out.println("m2-start");
m3();
System.out.println("m2-end");
}
public void m3()throws Exception{//消极处理,告诉调用者可能产生异常
System.out.println("m3-start");
System.out.println("m3-end");
//throw new RuntimeException();
}
public void setAge(int age){
if (age>0&&age<257){
this.age=age;
}else {
try {
RuntimeException E=new RuntimeException("234");//此时E仅仅是普通对象
throw E;}catch (Exception E) {//处理方案2:自定义处理
E.printStackTrace();//处理方案1:打印堆栈跟踪信息
System.out.println(E.getMessage());//处理方案
// 3:获取message作为异常原因
System.out.println("123");
System.out.println("----");
}
}
}
}
多重异常处理