异常
异常,指的是程序在执行过程中,出现的非正常的情况,最终会导致
JVM
的非正常终止在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象
,Java处理异常的方式是中断处理
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以
避免
的
Throwable
Throwable
类是Java语言中的所有错误和异常的基类。只有在这个类的实例对象(或其子类)由java虚拟机或者可以通过Javathrow
声明抛出。同样的,这类只或它的一个子类可以在catch
条款参数类型。为了编译时检查异常,Throwable
和任何子类Throwable
也没有任何RuntimeException
或Error
子类作为检查的异常。两子类的实例,
Error
和异常
,通常用来表示特殊的情况时有发生。通常情况下,这些实例是新创建的上下文中的特殊情况,以便包括相关的信息(如堆栈跟踪数据)。
异常体系
Error:严重问题,不需要处理
Exception:称为异常类,表示程序本身可以处理的问题
- RuntimeException:编译期是不检查的,出现问题后,需要返回
修改代码
- 非RuntimeException:编译期就
必须处理
的,否则程序不能通过编译,更不能正常运行
JVM的默认处理方案
如果程序出现问题,不做任何处理,最终
JVM
会做默认处理
- 把异常的名称,异常原因及异常出现的位置等信息输出在控制台
- 程序停止执行 如:java.lang.ArrayIndexOutOfBoundsException
异常处理
try...catch
- try...catch
语法
try{ 可能出现异常的代码; }catch (异常类名 变量名){ 异常的处理代码; }
执行流程:
程序从try里面的代码开始执行,出现异常,会自动生成一个
异常类对象
,改异常对象将被提交给Java运行时系统,当Java运行时系统接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理执行完毕之后,程序还可以继续往下执行
public class TEST { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); } public static void method(){ try { int[] arr = {1,2,3}; System.out.println(arr[3]); //不存在索引3 } catch (Exception e) { System.out.println("你访问的数组不存在"); //try如果异常则抛出catch内容 } } }
throws
throws
格式:throws 异常类名
throws处理运行时异常
public class TEST { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); } public static void method() throws ArrayIndexOutOfBoundsException{ int[] arr = {1,2,3}; System.out.println(arr[3]); //java.lang.ArrayIndexOutOfBoundsException 将报错信息输出在控制台 } }
- throws处理编译时异常
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TEST { public static void main(String[] args) { System.out.println("开始"); try { method(); //此处使用时需要使用try...catch...处理抛出的异常 } catch (ParseException e) { e.printStackTrace(); } System.out.println("结束"); } //throws ParseException 抛出异常之后,谁使用谁处理异常 public static void method() throws ParseException { String s = "2048-08-09"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //格式化日期对象 Date parse = sdf.parse(s); System.out.println(parse); } }
编译时异常和运行时异常
Java中的异常分为两大类:
编译时异常
和运行时异常
,也被称为受检异常
和非受检异常
所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常 [详细见上述Throwable的图片]
- 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
import java.text.SimpleDateFormat; import java.util.Date; public class TEST { public static void main(String[] args) { method(); } //编译时异常,必须显示处理,否则程序就会发生错误,无法通过编译 public static void method() { String s = "2048-08-09"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //格式化日期对象 Date parse = sdf.parse(s); //java:未报告的异常错误java.text.ParseException; 必须对其进行捕获或声明以便抛出 System.out.println(parse); } }
- 运行时异常:无需显示处理,也可以和编译时异常一样处理
public class TEST { public static void main(String[] args) { method(); } //运行时异常,可以和编译时异常一样处理,使用try...catch... public static void method(){ int[] arr = {1,2,3}; System.out.println(arr[3]); //java.lang.ArrayIndexOutOfBoundsException } }
- 总结,编译时异常和运行时异常都可以使用try...catch...处理
- 编译时异常必须要进行处理,两种处理方案:try...catch...或者throws,如果采用throws,将来谁调用谁处理异常
- 运行时异常可以不处理,出现问题后,需要我们回去修改代码
自定义异常
格式
public class 异常类名 extends Exception{ 无参构造 带参构造 } public class ScoreException extends Exception{ public ScoreException(){} public ScoreException(String message){ super(message); } }
//异常类 package Test; // Exception 为 RuntimeException 父类 所以此处为编译时异常 public class ScoreException extends Exception{ public ScoreException(){} public ScoreException(String message){ super(message); } } //////////////////////////////////////// //自定义异常类 package Test; import Test.ScoreException; public class Teacher { //使用throws Test.ScoreException 抛出异常类 public void checkScore(int score) throws ScoreException{ if (score<0 || score>100){ // 通过throw 抛出异常对象 // throw new ScoreException(); // 调用无参构造,控制台输出系统错误信息 throw new ScoreException("你给的分数有误"); //带参构造,控制台输出自定义异常 }else { System.out.println("分数正常"); } } } ///////////////////////////////////////// //测试类 package Test; import java.util.Scanner; public class TeacherTest { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入分数"); int score = sc.nextInt(); Teacher t = new Teacher(); try { t.checkScore(score); //此处为编译时异常。所以必须显示处理,使用try...catch...处理异常 } catch (ScoreException e) { e.printStackTrace(); } } }
throws和throw的区别
throws throw 用在方法声明后面,跟的是异常类 用在方法体内,跟的是异常对象名 表示抛出异常,由该方法的调用者来处理 表示抛出异常,由方法体内的语句处理 表示出现异常的一种可能性,并不一定会发生这些异常 执行throw一定抛出了某种异常
try...catch...finally...
finally:在异常处理时提供
finally块
来执行所有清楚操作。比如说IO流
中释放资源特点:被
finally
控制的语句一定会执行,除非JVM退出
try{ 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }finall{ 执行所有清除操作; } public class FileOutputStreamDemo04 { public static void main(String[] args) { FileOutputStream fos = null; //此处定义全局变量 try { fos = new FileOutputStream("fos.txt"); fos.write("hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { //如果不判断fos是否为null 当new FileOutputStream("fos.txt") 路径不存在时 会报空指针异常的错误 if (fos != null){ try { fos.close(); //释放资源 } catch (IOException e) { e.printStackTrace(); } } } } }