0基础Java学习过程记录——异常
一、异常介绍
1.基本概念
Java中,将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常)
2.执行过程发生的异常事件
(1)Error
Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverflowError(栈溢出)和OOM(out of memory),Error是严重错误,程序会崩溃。
(2)Exception
其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等。
Exception分为两大类:运行异常和编译异常。
3.运行时异常
(1)基本介绍
运行时异常,编译器不要求强制处理的异常。一般是指编程时的逻辑错误,是程序员应该避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
对于运行时异常可以不做处理,因为这类异常很普通,若全处理可能会对程序的可读性和运行效率产生影响。
(2)常见的运行时异常
1)NullPointerException 空指针异常
当应用程序试图在需要对象的地方使用 null时,抛出该异常
2)ArithmeticException 数学运算异常
当出现异常的运算条件时,抛出此异常
3)ArrayIndexOutOfBoundsException 数组下标越界异常
用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
4)ClassCastException 类型转换异常
当试图将对象强制转换为不是实例的子类时,抛出该异常。
5)NumberFormatException 数字格式不正确异常
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常,使用异常我们可以确保输入是满足条件数字。
4.编译异常
(1)基本介绍
编译异常是指在编译期间,就必须处理的异常,否则代码不能通过编译。
(2)常见的编译异常
1)SQLException 操作数据库时,查询表可能发生异常
2)IOException 操作文件时,发生的异常
3)FileNotFoundException 当操作一个不存在的文件时,发生异常
4)ClassNotFoundException 加载类,而该类不存在时异常
5)EOFException 操作文件,到文件末尾,发生异常
6)ILLegalArguementException 参数异常
二、异常处理
1.基本介绍
异常处理就是当异常发生时,对异常处理的方式。
2.异常处理的方式
(1)try-catch-finally
1)基本介绍
Java提供try和catch块来处理异常。try块用于包含可能出错的代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有多个数量的try…catch块。
package com.fighting.try_;public class TryCatch01 {public static void main(String[] args) {try {String str = "加油";int a = Integer.parseInt(str);System.out.println("数字:" + a);} catch (NumberFormatException e) {System.out.println("异常信息=" + e.getMessage());} finally {System.out.println("finally代码块被执行...");}System.out.println("程序继续...");}
}
2)基本语法
try {
//可疑代码
//将异常生成对应的异常对象,传递给catch块
}catch(异常){
//对异常的处理
}
3)使用细节
1.如果异常发生了,则异常发生后面的代码不会执行,直接进入到catch块。
2.如果异常没有发生,则顺序执行try的代码块,不会进入到catch。
3.如果希望不管是否发生异常,都执行某段代码(比如关闭连接,释放资源等)则使用-finally{}。
4.可以有多个catch语句,捕获不同的异常(进行不同的业务处理),要求父类异常在后,子类异常在前,比如(Exception在后,NullPointerException在前),如果发生异常,只会匹配一个catch。
5.可以进行try-finally配合使用,这种用法相当于没有捕获异常,因此程序会直接崩掉。应用场景就是执行一段代码,不管是否发生异常,都必须执行某个业务逻辑。
try{
}
finally{//总是执行
}
public class TryCatchDetail02 {public static void main(String[] args) {//1.如果try代码块可能有多个异常//2.可以使用多个catch分别捕获不同的异常,相应处理//3.要求子类异常写在前面,父类异常写在后面try {Person person = new Person();person = null;System.out.println(person.getName());int n1 = 10;int n2 = 0;int res = n1 / n2;} catch (NullPointerException e) {System.out.println("空指针异常=" + e.getMessage());} catch (ArithmeticException e) {System.out.println("算数异常=" + e.getMessage());} catch (Exception e) {System.out.println(e.getMessage());}}
}class Person {private String name = "jack";public String getName() {return name;}
}
public class TryCatchDetail03 {public static void main(String[] args) {try{int n1 = 10;int n2 = 0;System.out.println(n1 / n2);}finally {System.out.println("执行了finally...");//执行}System.out.println("程序继续执行...");//不执行,直接崩溃}
}
package com.fighting.try_;
import java.util.Scanner;/*** @version 1.0* @autor 疯小丢*/
public class TryCatchExercise04 {public static void main(String[] args) {//1.创建Scanner对象//2.使用无限循环,去接收一个输入//3.然后将该输入的值,转成一个int//4.如果在转换时抛出异常,说明输入的内容不是一个可以转成int的内容//5.如果没有抛出异常,则break 该循环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);}
}
4)try-catch-finally 执行顺序小结
1.如果没有出现异常,则执行try块中所有语句,不执行catch块中语句,如果有finally,最后还需要执行finally里面的语句。
2.如果出现异常,则try块中异常发生后,剩下的语句不再执行。将执行catch块中的语句,如果有finally,最后还需要执行finally里面的语句。
5)测试
如果try出异常没有try-catch或throw,其实在main后面还有个throws Exception,让JVM直接输出异常(没有显式使用try-catch和throw,默认throw)
finally必须执行,若前面catch执行并返回一个值,finally也执行并返回一个值,则catch返回的值被覆盖了,返回finally返回的值(catch中的return不会马上执行)。会输出return的值
(2)throws
1)基本介绍
如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可以是方法中产生的异常类型,也可以是它的父亲。
2)使用细节
1.对于编译异常,程序中必须处理,比如try-catch或者throws
2.对于运行时异常,程序中如果没有处理,默认就是throws的方式处理
3.子类重写父类的方法时,对抛出异常的规定:
子类重写的方法,所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型
4.在throws过程中,如果有方法try-catch,就相当于处理异常,就可以不必throws
package com.fighting.throws_;import java.io.FileInputStream;
import java.io.FileNotFoundException;/*** @version 1.0* @autor 疯小丢*/
public class ThrowsDetail {public static void main(String[] args) {}public void f2() /*throws ArithmeticException*/{//1.编译异常必须处理//2.运行时异常如果没有处理,默认就是throws方式处理int n1 = 10;int n2 = 0;double res = n1 / n2;}public static void f1() throws FileNotFoundException {//调用f3()报错//原因://因为f3()抛出的是一个编译异常//即这时就要求f1()必须处理这个编译异常//要么try-catch-finally,或者继续throwsf3();}public static void f3() throws FileNotFoundException {FileInputStream fis = new FileInputStream("d://aa.txt");}public static void f4() {//在f4中调f5()是OK//原因:f5()抛出的是运行异常//Java中有默认处理机制,不要求程序员显示处理f5();}public static void f5() throws ArithmeticException {}
}class Father {public void method() throws RuntimeException {}
}class Son extends Father {//3.子类重写父类方法时,对抛出的异常的规定://子类重写的方法所抛出的异常类型要么和父类抛出的异常一致//要么为父类抛出的异常的类型的子类型@Overridepublic void method() throws NullPointerException {}
}
三、自定义异常
1.基本概念
当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息
2.步骤
(1)定义类:自定义异常类名继承Exception或RuntimeException
(2)如果继承Exception,属于编译异常
(3)如果继承RuntimeException,属于运行异常(一般来说,继承RuntimeException)