异常

异常

异常的分类

java.lang.Throwable (顶级父类)

|——Error——————一般不编写针对性的代码进行处理

|——Exception——————可以进行异常处理

|——checked(编译时异常)

|——IOException

|——FileNotFoundException

|——ClassNotFoundException

|——unchecked(运行时异常)

|——NullpointerException

|——ArrayIndexOutOFBoundsException

|——ClassCastException

|——-NumberFormatException

|——InputMismatchException

|——ArithmeticException

运行时异常举例

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* @ClassName ExceptionTest
* @Description 运行时异常
* @Author renhongchang
* @Date 2021/7/22 15:57
* @Version 1.0
* @Blog https://rhc-rgb.github.io
*/
public class ExceptionTest {
//NullpointerException
@Test
public void test1(){
int[] arr = null;
System.out.println(arr[3]);

String str = null;
System.out.println(str.charAt(0));
}

//ArrayIndexOutOfBoundsException
@Test
public void test2(){
int[] arr = new int[10];
System.out.println(arr[10]);
}

//ClassCastException
@Test
public void test3(){
Object obj = new Date();
String str = (String)obj;
}

//NumberFormatException
@Test
public void test4(){
String str = "abc";
int a= Integer.parseInt(str);
}

//InputMismatchException
@Test
public void test5(){
Scanner scsn = new Scanner(System.in);
int score = scsn.nextInt();
System.out.println(score);

//输入 字符串 出现InputMismatchException 异常
}

//ArithmeticException
@Test
public void test6(){
int a = 5 / 0;
System.out.println(a);
}
}

编译时异常

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void test7(){
FileInputStream fileInputStream = new FileInputStream(new File("hello.txt"));


int i;

while((i= fileInputStream.read()) != -1){
System.out.println(i);
}

fileInputStream.close();
}

异常处理

抓抛模型

过程一 : ”抛“ —— 程序执行过程中,一大发现异常就会在异常代码出生成一个对应异常类的对象,并将此对象抛出。

​ 一旦抛出对象,其后代码不在执行。

过程二 : ”抓“ —— 抓可以理解为异常处理的方式 ①try - catch - finally ② Throws

try - catch - finally的使用

==try{==

​ ==可能出现异常的代码;==

==}catch (异常类型1 变量名1){==

​ ==处理异常的方式1;==

==} catch (异常类型2 变量名2){==

​ ==处理异常的方式2;==

==} catch (异常类型3 变量名3){==

​ ==处理异常的方式3;==

==}==

==…==

==finally{==

​ ==一定会执行的代码;==

==}==

  1. finally 是可选的

  2. 使用try将可能出现异常的代码包裹起来,在执行过程中,一旦出现异常,就会生成一个对应的异常类对象,根据此对象的类型去catch中匹配

  3. 一旦try中的异常匹配到某一个catch,就进入catch中进行异常处理,一旦处理完成,就跳出当前try - catch结构(没有finally),继续执行

  4. catch中的异常类型如果没有子父类关系,则谁在上谁在下没有无所谓;==如果满足子父关系,则子类必须在父类上边==

  5. 常用的异常处理方法:

    ① ==String getMessage()== 返回异常信息

    ② ==printStackTrace()==

  6. 在 try 中声明的变量,在 try 外边不能使用

  7. finally 中的代码一定会被执行,即使 catch 中又出现异常,try 中有return 或者 catch 中有 return 语句 finally 中的代码也会被执行。

    体会1:try - catch - finally 处理编译时异常,是程序编译时不报错,但是运行时仍然可能报错。相当于使用try - catch - finally结构将 一个编译时异常延迟到运行时。

    体会2:开发中,由于运行时异常比较常见,所以通常就不针对运行时异常 try - catch - finally 处理,针对编译时异常,一定要进行异 常处理。

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test1(){
String str = "123";
str = "abc";
try{
int num = Integer.parseInt(str);
}catch(NumberFormatException e){
System.out.println("数据类型是不是有一丢丢问题!!!");
}finally{

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void test2(){
String str = "123";
str = "abc";
try{
int num = Integer.parseInt(str);
}catch(NumberFormatException e){
System.out.println("数据类型是不是有一丢丢问题!!!");

return;
}finally{
System.out.println("我不管,我还会执行");
}
}

throws + 异常类型

  1. throws + 异常类型 写在方法的声明出,指明此方法执行时,可能会抛出的异常类型。一旦执行时出现异常,仍会在异常代码出生成一个异常,此对象满足 throws 后边的异常类型时就会被抛出。异常代码后续的代码就不再执行。

体会:try - catch - finally 真正将一场处理掉了。

​ throws 只是将异常抛给方法的调用者,并没有真正将异常处理掉。

开发中如何选择使用try - catch - finally 还是 throws 处理异常?

  1. 如果父类中被重写的方法没有使用 throws 处理异常,则子类重写的方法也不能使用 throws ,意味着子类异常必须使用 try - catch - finally 方式处理。
  2. 执行的方法中先后又调用了另外几个方法,建议这几个方法使用 throws 处理异常,执行的方法使用 try - catch - 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
27
public class SrudentTest {
public static void main(String[] args) {
Student s = new Student();
s.regist(-100);
System.out.println(s);
}
}

class Student{
private int id;

public void regist(int id){
if (id > 0){
this.id = id;
}else{
// System.out.println("您输入的非法!!!");
throw new RuntimeException("您输入的非法!");
}
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
'}';
}
}
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
27
28
29
30
31
32
public class SrudentTest {
public static void main(String[] args) {
try{
Student s = new Student();
s.regist(-100);
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}

}
}

class Student{
private int id;

public void regist(int id) throws Exception {
if (id > 0){
this.id = id;
}else{
// System.out.println("您输入的非法!!!");
throw new Exception("您输入的非法!");
}
}

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

用户自定义异常类

  • 如何自定义异常类:
    1. 继承于现有的异常结构,RuntimeException,Exception
    2. 提供serialVersionUID
    3. 提供重载构造器
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//异常类

public class MyException extends Exception{
static final long serialVersionUID = -3387516993124229948L;

public MyException(){

}
public MyException(String msg){
super(msg);
}
}



public class SrudentTest {
public static void main(String[] args) {
try{
Student s = new Student();
s.regist(-100);
System.out.println(s);
}catch(Exception e){
e.printStackTrace();
}

}
}

class Student{
private int id;

public void regist(int id) throws Exception {
if (id > 0){
this.id = id;
}else{
// System.out.println("您输入的非法!!!");
throw new MyException("不能输入负数");
}
}

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