}
非受检异常(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开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!