什么是异常?
程序中的异常,即在程序执行的过程中出现的非正常情况,如果不处理,最终会导致JVM的非正常停止
异常的抛出机制
Java中把不同的异常转化为不同的类,一旦发生异常,就创建该异常类型的对象,并且抛出(throw),然后程序员就可以捕获(catch)这个对象,如果没有捕获(catch)这个异常对象,那么这个异常对象就会导致程序的终止
我们该如何对待异常
1.不处理
2.一遇到就处理
异常的体系结构
Throwable类来处理异常
Throwable类一共有两个子类
1.Error
2.Exception
Error
Java虚拟机无法解决的严重问题,一般不编写代码进行处理
//Error出现的报错
StackOverflowError(栈空间溢出)
例如:无限递归
OutOfMemoryError(堆空间溢出,简称OOM)
byte[] arr = new byte[1024 * 1024 * 100];
//OutOfMemoryError:Java heap space
Exception
因编程错误或偶然的外在原因导致的一般性问题可以写代码解决
Exception可分为:1.编译时异常(checked异常、受检异常)
编译时异常即运行Java.exe时出现的异常
2.运行时期异常(即runtime异常、unchecked异常、非受检异常)
通常是写代码时出现的语法错误
编译时异常可具体分为
//编译时异常
//例子1:ClassNotFoundException
public void test07(){
Class c = Class.forName("java.lang.String"); //ClassNotFoundException
}
//例子2:FileNotFoundException && IOException
public void test10() {
File file = new File("如何养生.txt");
FileInputStream fis = new FileInputStream(file);// FileNotFoundException
int b = fis.read();//IOException
while(b != -1){
System.out.print((char)b);
b = fis.read();// IOException
}
fis.close();// IOException
}
}
运行时时异常可具体分为
//运行时异常
//例子1:NullPointerException
@Test
public void test01(){
//NullPointerException
int[][] arr = new int[3][];
System.out.println(arr[0].length);
}
//例子2:ClassCastException
@Test
public void test02(){
//ClassCastException
Object obj = 15;
String str = (String) obj;
}
//例子3:ArrayIndexOutOfBoundsException
@Test
public void test03(){
//ArrayIndexOutOfBoundsException
int[] arr = new int[5];
for (int i = 1; i <= 5; i++) {
System.out.println(arr[i]);
}
}
//例子4:InputMismatchException
@Test
public void test04(){
//InputMismatchException
Scanner input = new Scanner(System.in);
System.out.print("请输入一个整数:");//输入非整数
int num = input.nextInt();
input.close();
}
//例子5:ArithmeticException
@Test
public void test05(){
int a = 1;
int b = 0;
//ArithmeticException
System.out.println(a/b);
}
//例子6:NumberFormatException
@Test
public void test06(){
String str = "123";
int i = Integer.parseInt(str);
}
Java异常处理
将处理的程序代码集中在一起,与正常程序分开
Java异常处理的方式
1.try - catch - finally:直接处理异常(抓抛模型)
2.throws + 异常类型:甩锅给别人处理
try - catch - finally(抓抛模型)的使用
1.将可能出现异常的代码放入try中,一旦出现了异常,会自动生成一个对应异常类的对象,并抛出对象
2.对于try抛出的异常类对象,使用catch进行匹配,一旦匹配上,就进入catch语句进行处理,一旦处理结束,就接着往下执行
3.如果声明了多个catch结构,无子父类关系声明则位置随意;
有子父类关系,则子类要声明在父类结构上面,否则会报错
4. catch中异常处理方式:
(1):自己编写输出语句
(2):printStackTrace():打印异常的详细信息(推荐使用),和编译错误时显示的一致,只是使用该异常处理时会通过编译
(3):getMessage():获取发生异常的原因
For input String = "abc";
//try - catch - finally的基本结构
try{
...... //可能产生异常的代码
}
catch( 异常类型1 e ){
...... //当产生异常类型1型异常时的处置措施
}
catch( 异常类型2 e ){
...... //当产生异常类型2型异常时的处置措施
}
finally{
...... //无论是否发生异常,都无条件执行的语句
}
注意
1. try中的变量,出了try就不可以使用了
2.在开发中,运行时异常可以不用 try - catch - finally,可以直接报错来改代码,编译时异常一定要处理,否则编译不通过
2.编译时异常中,可以使用多态,只写父类异常即可
finally(无论发生异常,都要执行的代码)
1. 当在catch中出现异常时,有的程序就无法继续执行,此时就要使用finally
2. finally优先级比return高, 当catch中的return与下面代码都会输出时,一定要写finally
3. 当finally和catch中都存在return时,以finally中的return为准
4.同一个变量, catch中有return, final中没有return,返回值以有return的值为准
5. finally不可单独使用
6. finally和catch是可选的,一个程序可以有finally无catch,也可以有catch无finally,但是二者中一定要出现一个
7.我们在开发中有一些资源必须进行关闭的操作,这些关闭的操作一定要写在finally中
//应用
public class Test1 {
@Test
public void test06(){
try{
String str = "abc";
int i = Integer.parseInt(str);
System.out.println(i);
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("程序结束");
}
}
}
手动抛出异常对象
开发中出现不满足具体场景的代码问题,就要手动抛出异常对象
public class Test1 {
int id = -1;
@Test
public void test1 (int id) throws Exception {
if(id >= 0){
this.id = id;
}else{
//手动抛出异常对象
//方式1:
throw new Exception("输入的id非法 ");
//方式2:
//throw new RuntimeException("输入的id非法 ");
}
}
}
throw与throws的区别
throw:throw后代码不能被执行,编译不通过
throws:用在声明处,throws用在方法内部
自定义异常
定义
1.继承于现有的异常体系,通常继承于Runtime Exception / Exception
2.提供几个重载的构造器
3.提供一个全局变量,声明为static final long serialVersionUID`
为什么要自定义异常类
因为为了通过异常的名称就可判断异常出现的原因,通过原因判断出问题