目录
前言
Hi~ 你好!
欢迎点击我的博客 : )
这是我的学习总结,希望也能帮助到你
我的博客地址:hi~,我在这里~,欢迎关注哦,
三连不迷路,优质内容持续更新!
一. 异常的概念
在Java中,将程序执行过程中发生的不正常行为叫做异常
1.运行时异常
运行时异常,也称非受查异常 Unchecked Exception
System.out.println(10/0);//ArithmeticException ——by zero//算数异常
int[]arr = null;//引用不指向任何的对象
System.out.println(arr[1]);//NullPointerException 空指针异常
System.out.println("hello");//抛出异常之后,没有处理异常,后面的内容不能正常打印
int []arr ={1,2,3};
System.out.println(arr[10]);//ArrayIndexOutOfBoundsException 数组越界异常
运行时异常(非受查异常)
ArithmeticException ——by zero 算数异常
NullPointerException 空指针异常
ArrayIndexOutOfBoundsException 数组越界异常
这三者都是运行时异常,也称为(非受查异常)
抛出异常之后,没有处理异常,后面的内容不能正常打印
在Java中,不同类型的异常,都有对应的类来进行描述
2.编译时异常
编译时异常,也叫受查异常 Checked Exception
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();// CloneNotSupportedException 编译时异常 (受查异常)区别于语法错误,不一样滴
} //必须对其进行捕获或声明以便抛出
}//异常就是类
class Person implements Cloneable{//实现Cloneable接口
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//重写clone
}
}
CloneNotSupportedException 必须对其进行捕获或声明以便抛出
继承自extends Exception
这类异常叫编译时异常 (受查异常)在编译的时候报错
区别于语法书写时的错误,是不一样滴
3.异常的体系结构
Error 和 Exception 是顶层类的两个子类,一个负责错误,一个负责异常
Error:Java虚拟机无法解决的问题,如JVM内部错误,资源耗尽 eg.StackOverflowError
Exception: 可以人为代码解决的问题
二. 异常的处理
异常处理的主要关键字:throw try catch final throws
1.异常的抛出
1.代码自己执行的过程中,触发异常
2.自己手动抛出异常
public static void main(String[] args) {
func(null);
//Exception in thread "main" java.lang.NullPointerException
// at Learn.Test1.func(Test1.java:32)
// at Learn.Test1.main(Test1.java:26
}
public static void func(int[] a) {
if (a == null) {
throw new NullPointerException();//手动抛出一个空指针异常
}
}
手动抛出空指针异常 ,一般用在自定义异常
1.throw必须写在方法体内部
2.抛出的对象是Exception或它的子类
3.异常一旦抛出,后面的代码将不会执行
2.异常的捕获
2.1 异常声明throws
public static void main(String[] args) throws CloneNotSupportedException {//传递到main方法,同样声明来处理
func2(null);
System.out.println("test");//没有输出
//Exception in thread "main" java.lang.CloneNotSupportedException
// at Learn.Test1.func2(Test1.java:45)
// at Learn.Test1.main(Test1.java:38)
}
public static void func2 (int[] a) throws CloneNotSupportedException {//在方法后面通过throes声明异常
if (a == null) {
throw new CloneNotSupportedException();//受查异常 //在这里中断了
}
}
}//异常就是类
class Person implements Cloneable {//实现Cloneable接口
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();//重写clone
}
}
用throes在方法的后面进行声明,来表面方法内可能存在的异常
同时会随着方法传导到main方法,main方法同样需要进行声明
当前方法不处理异常,提醒方法的调用者处理异常 。如果方法内部抛出多个异常,声明时用逗号隔开
当没有代码没有解决这个异常时,就会交给JVM处理,程序奔溃
2.2 try-catch捕获处理
public static void main(String[] args) {//传递到main方法,同样声明来处理
try {
//存放可能出现异常是代码
func2(null);
// func(null);
}catch (CloneNotSupportedException e){//(异常的类型 变量)
// 对于受查异常来说,当try当中没有受查异常的时候catch检查不到就会报错
e.printStackTrace();//打印栈上的信息
//java.lang.CloneNotSupportedException
// at Learn.Test1.func2(Test1.java:55)
// at Learn.Test1.main(Test1.java:41)
System.out.println("捕捉到了CloneNotSupportedException异常,进行处理异常的逻辑");
}catch (NullPointerException e){
e.printStackTrace();
System.out.println("捕捉到了NullPointerException异常");
}catch (Exception e){
System.out.println("Exception兜底");
}
System.out.println("正常的逻辑");//此时,没有红字报错了,代码正常运行并打印后面的语句
}
public static void func2 (int[] a) throws CloneNotSupportedException {//在方法后面通过throes声明异常
if (a == null) {
//throw new NullPointerException();
throw new CloneNotSupportedException();//受查异常 //在这里中断了
}
}
在try中存放可能出现异常是代码
用catch捕获抛出的异常
对于受查异常来说,当try当中没有受查异常的时候catch检查不到就会报错
catch的多个异常如果有继承关系,父类在后
可以把Exception放在最后一个catch进行兜底
当try当中存在多个异常时,从上往下执行
try块抛出异常后,后面的代码不会执行如果catch中没有捕获到异常的话,将由JVM兜底,程序终止
2.3 finally
无论有没有异常,有的语句都需要执行,比如网络连接等,需要对资源进行回收,
异常引发的跳转可能会导致某些语句执行不到,这时就需要用到finally
public static void main(String[] args) {//传递到main方法,同样声明来处理
Scanner sc = new Scanner(System.in);
try {
int i = sc.nextInt();
int []arr ={1,2,3};
System.out.println(arr[2]);
System.out.println("test");
//存放可能出现异常是代码
func2(null);
// func(null);
}catch (CloneNotSupportedException e){//(异常的类型 变量)
// 对于受查异常来说,当try当中没有受查异常的时候catch检查不到就会报错
e.printStackTrace();//打印栈上的信息
//java.lang.CloneNotSupportedException
// at Learn.Test1.func2(Test1.java:55)
// at Learn.Test1.main(Test1.java:41)
System.out.println("捕捉到了CloneNotSupportedException异常,进行处理异常的逻辑");
}catch (NullPointerException e){
e.printStackTrace();
System.out.println("捕捉到了NullPointerException异常");
}catch (Exception e){
System.out.println("Exception兜底");
}
try {
func(null);
}catch (NullPointerException e){
e.printStackTrace();
System.out.println("捕捉到了NullPointerException异常");
}finally {
sc.close();
System.out.println("执行finally语句");//不管是否在try中抛出异常,finally都会执行,一般用于资源的释放
}
System.out.println("正常的语句");//此时,没有红字报错了,代码正常运行并打印后面的语句
}
输出结果:
4
3
test
捕捉到了CloneNotSupportedException异常,进行处理异常的逻辑
捕捉到了NullPointerException异常
执行finally语句
正常的语句
java.lang.CloneNotSupportedException
at Learn.Test1.func2(Test1.java:79)
at Learn.Test1.main(Test1.java:49)
java.lang.NullPointerException
at Learn.Test1.func(Test1.java:91)
at Learn.Test1.main(Test1.java:65)
Process finished with exit code 0
不管是否在try中抛出异常,finally都会执行,一般用于资源的释放
不建议在finally当中写return
面试题
1.throw和throws的区别是什么?
throw抛出异常,throws声明异常
2.finally当中的语句一定会执行吗?
一定会执行
3.异常的处理流程
如果本方法中没有合适的处理异常的方式,会沿着调用栈向上传递
方法之间是存在相互调用关系。 用 " 调用栈 " 来描述 . 在 JVM 中有一块内存空间称为 "虚拟机栈 " 专门存储方法之间的调用关系 . 当代码中出现异常的时候 , 我们就可以使用 e.printStackTrace(); 的方式查看出现异常代码的调用栈
异常处理流程:
1.程序先执行try当中的代码
2.如果出现异常,结束try当中的代码,看和catch是否匹配
3.如果匹配到异常类型,执行catch中的代码
4.如果没有匹配到异常类型,向上传递到上层调用者
5.不管有没有匹配,finally的代码都会执行
6,直到传导main也没有处理,由JVM兜底,程序异常终止
4. 自定义异常类
自定义异常类,然后继承自 Exception 或者 RunTimeException实现一个带有 String 类型参数的构造方法,参数含义:出现异常的原因
public class Test2 {
public String username = "admain";
public String password ="123";
public void login(String username,String password)throws UserNameException{
if(!this.username.equals(username)){
System.out.println("用户名错误");
throw new UserNameException("用户名错了");
}
if(!this.password.equals(password)){
System.out.println("密码错误");
throw new PassWordException("密码错了");
}
}
public static void main(String[] args) {
Test2 test2 = new Test2();
try {
test2.login("admin","123");//用户名不对
}catch (UserNameException e){
e.printStackTrace();
System.out.println("用户名异常");
}catch (PassWordException e){
e.printStackTrace();
System.out.println("密码异常");
}
finally {
}
}
}
用户名错误
用户名异常
Learn.UserNameException: 用户名错了
at Learn.Test2.login(Test2.java:9)
at Learn.Test2.main(Test2.java:21)
继承自 Exception 的异常默认是受查异常继承自 RuntimeException 的异常默认是非受查异常
后记
看到这里,希望能帮到你~
您的点赞 ,收藏 ,关注 是我创作的最大动力!
同时也欢迎在评论区进行交流,共同进步~