Java异常机制

1.子类/实现类的重写方法可以不声明异常

2.如果子类/实现类的重写方法必须要声明异常,则必须和父类被重写方法的声明异常相同或是它的子类

对于父类只声明多个异常的方法

class Super{

public void test() throws IOException,SQLException {

}

}

class Base1 extends Super{

@Override

public void test() {

}

}

class Base2 extends Super{

@Override

public void test() throws IOException,SQLException{

}

}

class Base3 extends Super{

@Override

public void test() throws IOException{

}

}

class Base4 extends Super{

@Override

public void test() throws SQLException{

}

}

class Base5 extends Super{

@Override

public void test() throws FileNotFoundException,SQLException{

}

}

1.子类/实现类的重写方法可以不声明异常

2.如果子类/实现类的重写方法必须要声明异常,则可以是父类被重写方法的多个声明异常中的某些个,或者全部的本身(或其子类)。

抛出异常

====

自动抛出异常


当程序中出现异常时,系统会自动产生一个异常对象,并抛出给Java运行时环境。Java运行时环境获取检查是否有捕获异常或声明抛出异常,如果有,则异常被相应处理。否则会被直接抛出给JVM处理。

public class Test {

public static void main(String[] args) {

int a = 100;

int b = 0;

System.out.println(a/b);

}

}

运行结果:

Exception in thread “main” java.lang.ArithmeticException: / by zero

at exceptionTest.checkedExceptionTest.Test.main(Test.java:7)

throw抛出异常


除了自动抛出异常外,Java允许程序自行抛出异常。此时使用thorw关键字。

定义格式

thorw 异常对象;

public class Test {

public static void main(String[] args) {

int a = 100;

int b = 0;

if(b==0){

throw new ArithmeticException(“除法运算中,除数不能为0”);

}

System.out.println(“-----------------”);

System.out.println(a/b);

}

}

运行结果:

Exception in thread “main” java.lang.ArithmeticException: 除法运算中,除数不能为0

at exceptionTest.checkedExceptionTest.Test.main(Test.java:8)

throw抛出异常的特点

1.throw抛出的是异常对象,且只能抛出一个异常对象。

2.throw抛出异常后,会终止当前程序的运行。

3.如果throw抛出的异常是非受检异常,则程序所在方法不需要强制处理异常

4.如果throw抛出的异常是受检异常,则程序所在方法需要强制显示处理异常,或显示声明抛出异常

public class Test {

public static void main(String[] args) throws FileNotFoundException {

test(null);

}

private static void test(String str) throws FileNotFoundException {

if(str == null){

throw new FileNotFoundException(“指定文件地址不存在”);

}

}

}

捕获异常

====

程序出现了异常,除了可以声明抛出异常给上级调用者处理外,还可以程序自己捕获该异常。

try…catach捕获异常


定义格式

try {

可能出现异常的代码;

}

catch ( 异常类名1 异常变量名 ) {

处理异常的代码;

}

catch ( 异常类名2 异常变量名 ) {

处理异常的代码;

}

catch ( 异常类名n 异常变量名 ) {

处理异常的代码;

}

其中try块和catch块的大括号不能删除,就算try和catch中只有一条语句,也要保留{}。

另外try,catch中可以继续嵌套try…catch捕获异常。

catch特点

1.一个try可以对应多个catch

2.只有一个catch块会被执行,catch块执行完后,程序结束。

3.多个catch的排序有要求,小类异常在前,大类异常在后,否则编译报错。对于同级异常可以不分顺序。

public class Test {

public static void main(String[] args) {

try{

new FileInputStream(“a.txt”);//系统产生FileNotFoundException异常类型对象

System.out.println(“---------------------”);

new SimpleDateFormat(“yyyy-MM”).parse(“2020-aa”);

System.out.println(“+++++++++++++++++++++”);

} catch (ParseException e) {//ParseException和IOException都是Exception的子类,且二者间没有继承关系,所以catch部分先后顺序

System.out.println(“格式转化异常”);

} catch (IOException e){//FileNotFoundException异常类型对象是IOException的子类,所以执行该catch块代码,执行完后,程序终止

System.out.println(“文件不存在”);

} catch (Exception e) {// 该Catch块不能放在前面,因为Exception是IOException,必须放在IOException的catch块后面

System.out.println(“其他异常”);

}

}

}

4.对于同级异常可以不分顺序,也可以用"|"使用同一个catch定义多个同级异常

public class Test {

public static void main(String[] args) {

try{

new FileInputStream(“a.txt”);

System.out.println(“---------------------”);

new SimpleDateFormat(“yyyy-MM”).parse(“2020-aa”);

System.out.println(“+++++++++++++++++++++”);

} catch (ParseException | IOException e) {//同级异常可以使用"|"并列定义

System.out.println(“文件找不到或格式转化异常”);

} catch (Exception e) {

System.out.println(“其他异常”);

}

}

}

5.catch块中定义的异常类型变量,默认被final修饰

public class Test {

public static void main(String[] args) {

try{

new FileInputStream(“a.txt”);

System.out.println(“---------------------”);

new SimpleDateFormat(“yyyy-MM”).parse(“2020-aa”);

System.out.println(“+++++++++++++++++++++”);

} catch (ParseException | IOException e) {

//e = new IOException();//Cannot assign a value to final variable 'e

System.out.println(“文件找不到或格式转化异常”);

} catch (Exception e) {

System.out.println(“其他异常”);

}

}

}

关闭资源

====

我们在try块中打开数据库连接,文件,或者网络连接这些物理资源的话,使用完必须关闭这些物理资源。而物理资源不是对象,无法被垃圾回收器自动销毁,而需要显示关闭。

那么try中打开了物理资源,可以在哪里关闭这些资源呢?

如果在try,catch块中关闭资源,那么关闭资源操作可能会得不到执行机会。

1.因为try中代码出现异常的话,则异常后面的代码不会被执行。

2.每次只有一个catch块会得到执行机会,其他catch块不会被执行。

所以Java提供了finally关键字。

finally关键字的使用


public class Test {

public static void main(String[] args) {

FileInputStream fis = null;

try{

fis = new FileInputStream(“D:\文档\IdeaProjects\JavaSE\out\production\JavaSE\exceptionTest\checkedExceptionTest\a.txt”);

} catch (FileNotFoundException e) {

System.out.println(“文件不存在”);

} finally {

if(fis != null){

try {

System.out.println(“开始关闭资源”);

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

finally特点


1.finally本质作用是用来关闭try块中打开的资源

2.finally块一定会被执行,除非关闭JVM

public class Test {

public static void main(String[] args) {

try {

System.out.println(“try …”);

} finally {

System.out.println(“finally …”);

}

}

}

/**

  • 运行结果

  • try …

  • finally …

*/

public class Test {

public static void main(String[] args) {

try {

System.out.println(“try …”);

System.exit(1);//终止JVM

} finally {

System.out.println(“finally …”);

}

}

}

/**

  • 运行结果

  • try …

*/

3.finally块优先于try或catch块中的return执行

public class Test {

public static void main(String[] args) {

try {

System.out.println(“try …”);

return;

} catch (Exception e) {

System.out.println(“catch …”);

return;

}

finally {

System.out.println(“finally …”);

}

}

}

/**

  • 运行结果

try …

finally …

*/

public class Test {

public static void main(String[] args) {

try {

System.out.println(“try …”);

throw new Exception();

} catch (Exception e) {

System.out.println(“catch …”);

return;

}

finally {

System.out.println(“finally …”);

}

}

}

/**

  • 运行结果

try …

catch …

finally …

*/

4.如果finally,try,catch中都有return定义,则try,catch中的return失效,只有finally的return有效。

public class Test {

public static void main(String[] args) {

System.out.println(test());//3

}

private static int test() {

try {

return 1;

} catch (Exception e) {

return 2;

} finally {

return 3;

}

}

}

JDK7强化的关闭资源操作 try-close-resource


由于finally关闭资源的代码比较冗余,且比较规范重复。所以JDK7增强了try的功能,即在try中也可以关闭try打开的资源。

但是try关闭资源的前提是:资源类必须实现了Closeable或者AutoCloseable接口。

好消息是JDK7将大部分资源类/接口都实现了Closeable或者AutoCloseable接口。

public class Test {

public static void main(String[] args) throws FileNotFoundException {

try (

FileInputStream fis = new FileInputStream(“D:\文档\IdeaProjects\JavaSE\out\production\JavaSE\exceptionTest\checkedExceptionTest\a.txt”)

) {

fis.read();

} catch (IOException e) {

e.printStackTrace();

}

}

}

JDK7的try-close-resource语法就是在try后面加一个(),并在()中打开资源。当try块执行完成后,会自动关闭try打开的资源。

这只是一个语法糖,并不是什么新能力,可以看编译后代码,发现,其实try-close-resource本质还是使用finally关闭资源

import java.io.FileInputStream;

import java.io.IOException;

public class Test {

public Test() {

}

public static void main(String[] args) {

try {

FileInputStream fis = new FileInputStream(“D:\文档\IdeaProjects\JavaSE\out\production\JavaSE\exceptionTest\checkedExceptionTest\a.txt”);

Throwable var2 = null;

try {

fis.read();

} catch (Throwable var12) {

var2 = var12;

throw var12;

} finally {

if (fis != null) {

if (var2 != null) {

try {

fis.close();

} catch (Throwable var11) {

var2.addSuppressed(var11);

}

} else {

fis.close();

}

}

}

} catch (IOException var14) {

var14.printStackTrace();

}

}

}

处理异常

====

我们一般在catch捕获到异常后,直接继续在catch块中处理异常。我们常说的处理异常,其实是处理捕获到的异常对象。

关于异常对象的处理,主要就是异常对象的几个常用方法:

1.getMessage()  获取异常信息

2.printStackTrace() 输出异常跟踪栈信息到标准错误输出

3.printStackTrace(PrintStream s)  输出异常跟踪栈信息到指定输出流

3.getStactTrace() 获取异常跟踪栈信息

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.text.ParseException;

public class CheckedExceptionTest {

public static void main(String[] args) throws ParseException, FileNotFoundException {

ioExceptionTest();

}

private static void ioExceptionTest() {

try {

new FileInputStream(“a.txt”);

} catch (FileNotFoundException e) {

System.out.println(e.getMessage());

/**

  • a.txt (系统找不到指定的文件。)

*/

e.printStackTrace();

/**

  • java.io.FileNotFoundException: a.txt (系统找不到指定的文件。)

  • at java.io.FileInputStream.open0(Native Method)

  • at java.io.FileInputStream.open(FileInputStream.java:195)

  • at java.io.FileInputStream.(FileInputStream.java:138)

  • at java.io.FileInputStream.(FileInputStream.java:93)

  • at exceptionTest.checkedExceptionTest.CheckedExceptionTest.ioExceptionTest(CheckedExceptionTest.java:15)

  • at exceptionTest.checkedExceptionTest.CheckedExceptionTest.main(CheckedExceptionTest.java:10)

*/

System.out.println(e.getStackTrace());

/**

  • [Ljava.lang.StackTraceElement;@4554617c

*/

}

}

}

自定义异常

=====

Java异常除了原生异常类外,还可以自定义异常类。

并且自定义异常也可分为受检异常和非受检异常。

自定义受检异常类:只需要将自定义的异常类继承自Exception类。

自定义非受检异常类:只需要将自定义的异常类继承自RuntimeException类。

参考IOException的定义,我们可以发现自定义异常只需要定义几个构造器即可

public

class IOException extends Exception {

static final long serialVersionUID = 7818375828146090155L;

public IOException() {

super();

}

public IOException(String message) {

super(message);

}

public IOException(String message, Throwable cause) {

super(message, cause);

}

public IOException(Throwable cause) {

super(cause);

}

}

分别定义

无参构造器,

带一个String message构造器,其中message就是getMessage()方法的返回值。

带一个Throwable cause构造器,其中cause是原始异常。即自定义异常可以基于原始异常来定义。

带String message,Throwable cause的构造器,即有自定义的异常信息,也有原始异常信息。

异常链


由于原生异常会暴露一些敏感信息,如SQLException会暴露持久化层表结构信息,IOException会暴露文件系统信息,所以不建议直接将原生异常抛出给外部。

所以我们可以将原始异常信息记录下来,对外抛出一个不含敏感信息的自定义异常。

如果我们希望将自定义异常和原始异常建立联系,则可以在自定义异常中提供类似于public IOException(Throwable cause)的构造器。这样就可以保证异常栈信息的不中断。

public class Test {

public static void main(String[] args) throws FileNotFoundException {

try {

new FileInputStream(“D://a.txt”);

} catch (FileNotFoundException e) {

throw e;

}

}

}

如上代码抛出的异常会带有敏感信息:文件路径

Exception in thread “main” java.io.FileNotFoundException: D:\a.txt (系统找不到指定的文件。)

at java.io.FileInputStream.open0(Native Method)

at java.io.FileInputStream.open(FileInputStream.java:195)

at java.io.FileInputStream.(FileInputStream.java:138)

at java.io.FileInputStream.(FileInputStream.java:93)

at exceptionTest.checkedExceptionTest.Test.main(Test.java:10)

public class Test {

public static void main(String[] args) throws DefException {

try {

new FileInputStream(“D://a.txt”);

} catch (FileNotFoundException e) {

throw new DefException(“文件不存在”);

}

}

}

class DefException extends Exception{

public DefException() {

}

public DefException(String message) {

super(message);

}

public DefException(String message, Throwable cause) {

super(message, cause);

}

public DefException(Throwable cause) {

super(cause);

}

}

通过抛出自定义异常,可以防止敏感信息的泄露

Exception in thread “main” exceptionTest.checkedExceptionTest.DefException: 文件不存在

at exceptionTest.checkedExceptionTest.Test.main(Test.java:12)

import java.io.FileInputStream;

import java.io.FileNotFoundException;

public class Test {

public static void main(String[] args) throws DefException {

try {

new FileInputStream(“D://a.txt”);

} catch (FileNotFoundException e) {

throw new DefException(“文件不存在”,e);

}

}

}

class DefException extends Exception{

public DefException() {

}

public DefException(String message) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
class Test {

public static void main(String[] args) throws DefException {

try {

new FileInputStream(“D://a.txt”);

} catch (FileNotFoundException e) {

throw new DefException(“文件不存在”,e);

}

}

}

class DefException extends Exception{

public DefException() {

}

public DefException(String message) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-cBYjuYNW-1713162699687)]

[外链图片转存中…(img-ZI41MwwA-1713162699688)]

[外链图片转存中…(img-f8AeGmoH-1713162699688)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值