0%

java-Day7——异常

异常定义

指的是程序在执行过程中,出现的非正常情况,如果补处理最终会导致JVM的非正常停止。

异常的抛出机制

java中把不同的异常用不同的类表示,一旦发现某种异常,就创建该异常类型的对象,并throw。然后程序员可以catch到这个异常并处理;如果没有catch这个异常对象,那么这个异常对象将会导致程序的终止

如何对待异常

  • 一遇到错误就终止程序的运行

  • 编写程序时,充分的预防和避免。实在无法避免的,编写相应的代码进行异常的检测、以及‘异常的处理‘,保证代码的健壮性

异常的体系结构

Throwable类

是java执行过程总发生异常事件对应的类的根父类

Error和Exception

  • Error:java虚拟机无法解决的严重问题。如JVM系统内部错误、资源耗尽等严重情况。一般不编写针对性代码处理

    • StackOverflowError, OutOfMemoryError
  • Exception:其他因编程错误或偶然的外在因素导致的一般性问题,需要使用针对性的代码进行处理,使程序继续运行。否则一旦发生异常,程序也会挂掉。如空指针访问、试图读取不在的文件、网络连接中断。

    • 编译时异常:执行javac.exe命令时出现异常
      • ClassNotFoundException
      • FileNotFoundException
      • IoException
    • 运行时异常:执行java.exe命令时出现异常
      • ArrayIndexOutOfBoundsException
      • NullPointerException
      • ClassCastException
      • NumberFomatException
      • InpuitMismatchException
      • ArithmeticException

编译时异常和运行时异常

  • 编译时异常(checked异常):在代码编译阶段,编译器就能明确警示当前代码可能发生xx异常,并且明确督促程序员提前编写处理它的代码。 如果程序员没有编写对应的处理代码,则编译器就会直接判定编译失败,从而不能生产字节码文件。这类异常的发生不是由程序员的代码引起的或者不是靠加简单判断可以避免的。如FileNotFoundException

  • 运行时异常(runtime异常):在代码编译阶段,编译器完全不做任何检查,无论该异常都不给任何提示。只有等代码运行起来并确实发生了xx异常,它才能被发现。通常,这类异常是由程序员的代码编写不当引起的。RuntimeException

Java异常处理的方式

方式一 try-catch-finally

  1. “抛”:程序执行过程中,一旦出现异常,就会在异常的代码处,生产对应异常类的对象,并将对象抛出,一旦抛出,此程序就不执行其后的代码了。
  2. “抓”:针对于1中抛出的异常,进行捕获处理。一旦将异常进行了处理,代码就可以正常处理

基本结构

1
2
3
4
5
6
7
8
9
10
11
12
try{
...//可能产生异常的代码
}
catch(异常类型1){
...//产生异常1类型时的处理方式
}
catch(异常类型2){
...//产生异常2类型时的处理方式
}
finally{
...//无论是否发生异常,都无条件执行的语句
}

使用细节:

  • 如果声明了多个catch结构,不同的异常类型若不存在父子关系的情况下,声明位置无所谓。如果多个异常类型满足父子关系的,则必须将子类声明在父类结构的上面。

  • try中声明的变量,出了try结果后,就不可以进行调用了

  • try catch结构是可以嵌套的

Catch中处理异常的方式

  1. 自己编写输出的语句

  2. printStackTrace():打印异常详细信息。(推荐)

  3. getMessage():获取发生异常的原因

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void test1(){
try {
String str = "123";
str = "abc";
int i = Integer.parseInt(str);
System.out.println(i);
}catch (NumberFormatException e){
e.printStackTrace();
System.out.println(e.getMessage());

}
System.out.println("程序结束");
}

开发体会:

  • 运行时异常:

    ​ 开发中,通常就不进行显示的处理。一旦在程序执行中,出现了异常,就根据异常的提升信息修改代码。

  • 编译时异常:

    ​ 一定要处理,否则编译不过。

finally的理解

  • 将一定要执行的代码声明在finally结构中

  • 无论try或catch中是否存在仍未被处理的异常,无论try中或catch中是否存在return语句等,finally中声明的语句一定会执行

  • finally语句和catch语句是可选的,但finally不能单独使用

什么代码一定要放入finally

输入流、输出流、数据库连接、Socket连接等资源,在使用完以后,必须是显式的进行关闭操作,否则GC不会自动的回收这些资源,进而导致内存的泄露

方式二:throws

格式: 在方法的声明处,使用throws 异常1,异常2,…

是否真正处理了异常:

  • 从编译是否能通过的角度看,看成给出了异常万一要是出现时候的解决方法。此方案就是,继续向上抛出
  • 但是此throws方式,仅是将可能出现的异常抛给方法的调用者。此调用者仍然需要考虑如何处理相关异常,从这个角度看,throws的方式不算真正意义上处理了异常。

方法重写时的要求(针对于编译时异常):

子类重写方法抛出的异常类型要么与父类的方法抛出的异常相同或者是该异常类型的子类

开发中如何选择异常处理方法

  • 涉及资源的调用(流、数据库连接、网络连接),try-catch-finally,从而保证内存不泄露
  • 父类被重写的方法没有throws异常类型,子类重写方法出现异常只能使用try-catch-finally
  • 开发中方法a依次调用b,c,d等方法,方法b,c,d之间是递进关系。此时如果b,c,d中有异常,我们通常选择使用throws,而方法a中通常使用try-cat-finally

手动throw异常对象

在实际开发中,如果出现不满足具体场景的代码问题,我们就有必要抛出一个指定类型的异常对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class StudentTest {
public static void main(String[] args) {
Student s1 = new Student();
s1.regist(-10);
System.out.println(s1);
}
}

class Student{
int id;

public void regist(int id) {
if (id > 0) {
this.id = id;
}else{
throw new RuntimeException("输入ID非法");
}
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}

自动抛和手动抛异常的理解

  • 自动抛:程序执行过程中,一旦出现异常,就会在异常的代码处,自动生产对应异常类的对象,并将对象抛出
  • 手动抛:程序执行过程中,不满足指定条件的情况下,我们主动使用throw+异常类的对象方式抛出异常对象。

抓:

  • 狭义理解:try-catch的方式捕获异常,并处理
  • 广义理解:抓可以理解为“处理“。则此时对应着1.try-catch-finally 2.throws

自定义异常:

定义方式

  1. 通常继承于RuntimeException、Exception

  2. 通常提供几个重载的构造器

  3. 提供一个全局常量,声明为static final long serialVersionUID

使用方式

  • 在具体代码中,满足指定条件的情况下,需要收到的使用“throw+自定义异常类的对象”方法,将异常对象抛出。
  • 如果自定义异常类是非运行时异常,则必须考虑如何处理此异常类的对象(1.try-cat-finally 2.throws)

自定义异常的目的

通过异常的名称就能直接判断此异常出现的原因。尽然如此,我们就有必要在实际开发场景中,不满足我们指定条件时,知名我们自己特有的异常类,通过异常类的名称,就能判断出具体出现的问题

常见问题:

1.throw 和throws的区别

形:

throw:使用在方法内部,throw异常类的对象

throws:使用在方法的声明处,”throws 异常类1, 异常类2”

作用:

一个抛,一个是抓

2.java的异常体系结构,异常顶级接口是什么,exception下有哪些类

3.java异常处理机制

两种处理方案,try-catch-finally; throws

4.运行异常与一般异常区别

运行时异常:RuntimeException

  • 编译可以通过,运行时可能抛出。出现概率高一些;一般针对于运行时异常,都不处理

一般异常:Exception

  • 编译不能通过,要求必须在编译之前,考虑异常的处理。不处理编译不通过。

5.常见的异常

6.final、finally、finalize的区别

7.不适用try-catch,程序出现异常会如何?

对当前方法来讲,如果不适用try-catch,则在出现异常对象以后会抛出此对象。如果没有处理方案,就会终止程序的执行

8.try,catch捕获的是什么异常?

Exception。非error

9.如果执行finally代码块之前返回了结果或者Jvm退出了,此时finally代码块还会执行吗?

一定会执行。除了system.exit(0)

10.try语句中有return语句,最后写finally语句,finally语句中的code会不会执行?何时执行?如果执行是在return前还是后

会。先执行finally代码在return出结果

-------------本文结束感谢您的阅读-------------