Java异常机制(1)

}

非受检异常(RuntimeException)


非受检异常是在运行期才会抛出的异常,编译期间不强制显示处理该异常。

常见的非受检异常有NullPointerException,ClassCastException,ArrayIndexOutOfBoundsException,ArithmeticException,ConcurrentModificationException,IllegalArgumentException

import java.util.ArrayList;

import java.util.HashMap;

public class RuntimeExceptionTest {

public static void main(String[] args) {

// arithmeticExceptionTest();//Exception in thread “main” java.lang.ArithmeticException: / by zero

// nullPointerExceptionTest();//Exception in thread “main” java.lang.NullPointerException

// classCastExceptionTest();//Exception in thread “main” java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.Integer

// arrayIndexOutOfBoundsException();//Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 3

// illegalArgumentException();//Exception in thread “main” java.lang.IllegalArgumentException: Illegal Capacity: -1

// concurrentModificationException();//Exception in thread “main” java.util.ConcurrentModificationException

}

private static void concurrentModificationException() {

ArrayList list = new ArrayList<>();

list.add(“123”);

for (String s : list) {

list.add(“456”);

}

}

private static void illegalArgumentException() {

ArrayList list = new ArrayList<>(-1);

}

private static void arrayIndexOutOfBoundsException() {

Integer[] arr = new Integer[3];

arr[3] = 10;

}

private static void classCastExceptionTest() {

Integer i ;

Object obj = new Object();

i = (Integer) obj;

}

private static void nullPointerExceptionTest() {

HashMap hm = null;

hm.put(1,2);

}

private static void arithmeticExceptionTest() {

int a = 100;

int b = 0;

System.out.println(a/b);

}

}

声明异常

====

定义格式


[修饰符] 返回值类型 方法名(形参列表)throws 异常类1,异常类2,异常类3[,异常类n]

[修饰符] 构造器名 (形参列表) throws 异常类1,异常类2,异常类3[,异常类n]

声明异常使用关键字throws,可以在方法或构造器后面声明,且可以声明一个或多个异常。

声明的异常可以是受检异常,也可以是非受检异常。

下面是受检异常的throws声明

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.text.ParseException;

import java.text.SimpleDateFormat;

public class CheckedExceptionTest {

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

parseExceptionTest();

ioExceptionTest();

}

private static void ioExceptionTest() throws FileNotFoundException {

new FileInputStream(“a.txt”);

}

private static void parseExceptionTest() throws ParseException {

SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy-MM-dd”);

simpleDateFormat.parse(“2021-04-01”);

}

}

可能抛出受检异常的程序,如果没有自己去捕获处理异常,则必须使用throws关键字抛出该异常给上级调用者。

下面是非受检异常的throws声明

public class RuntimeExceptionTest {

public static void main(String[] args) {

arithmeticExceptionTest();

}

private static void arithmeticExceptionTest() throws ArithmeticException {

int a = 100;

int b = 0;

System.out.println(a/b);

}

}

可能抛出非受检异常的程序,由于非受检异常无需强制在编译期间处理,所以这里可以不做捕获异常,或声明异常的动作。如main方法中调用了arithmeticException方法时,虽然arithmeticException方法可能抛出非受检异常,但是main方法不需要强制处理。

但是声明抛出该异常给上级调用者也是可以的,如arithmeticException方法。

声明异常的意义


我们编写程序时大部分精力都放在业务代码上,而不是放在考虑无法穷尽的异常代码上,为了提供一种方便的思路去快速处理未知的异常,声明抛出可能的异常是一种好方法。

因为声明抛出异常后,我们在编写代码时就无需考虑处理该异常,而是将异常处理交给调用该方法的调用者。

声明异常的方法重写规则


我们知道方法重写时有一个规则:两同两小一大。其中两小就有关于父类/接口方法的异常的要求。

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

class Super{

public void test() throws IOException {

}

}

class Base1 extends Super{

@Override

public void test() {

}

}

class Base2 extends Super{

@Override

public void test() throws IOException{

}

}

class Base3 extends Super{

@Override

public void test() throws FileNotFoundException{

}

}

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 {

最后

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

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

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

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

} 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 {

最后

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

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

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

[外链图片转存中…(img-rx8x0QJ5-1715740116575)]

[外链图片转存中…(img-K1hIox1f-1715740116575)]

[外链图片转存中…(img-4GxXNueR-1715740116576)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值