java基础(十)

程序员就是不停的deBug,而这些Bug也就被我们称为异常。

了解异常

异常是为了预见在运行程序时可能会出现的问题,有问题安全退出程序的机制。所以的异常都有一个父类Throwable类,当然它也继承其他接口,但那个接口没有任何属性和方法。而Throwable又被两个类继承。分别是Error和Exception。

Error一般是编译器或虚拟机的问题,这个无解。我们能做的就是把编译器关闭后重新打开,严重的要重装JDK。

Exception也分为两类,一类是非运行时异常,另一类是运行时异常。

非运行时异常在编译时,编译器就可以提示我们,比如把整型赋值给字符串,少打符号或者中英的符号没区别开等等,编译器提示的错。

运行时异常,是我们编译运行后,进行该行代码运行时,出现了错误。比如:”ArithmeticException”、”ArrayIndexOutOfBoundsException”、”NullPointerException”等等等。这些都是我们常见的异常,算数异常、数组下标越界、空指针等等。而我们今天记录的就是提前发现运行时异常。

为啥学异常

当我们在处理数据时,尤其后面要学的流,很可能会出现很多错误,比如文件找不到,硬盘装不下,格式不匹配呀等等异常。很可能处理一行代码,就要做不断的判断。异常机制帮助我们,你做好开发就行,有问题交给Exception和它的子类去做。下面是简单的异常。

1
2
3
4
5
6
public static void main(String[] args){

int a = 1;
int b = 0;
if(b!=0) System.out.println(a/b);
}

因为整数除以0,是无限大或无限小的数,无法表示的数,所以会报ArithmeticException异常,算数异常。我们可以提前预判,手动处理被除数是否为0。

而有些类或方法,必须要捕获异常和抛出异常,才能正常使用,否则编译器也会报错。这就是我们接下来学的异常,它属于运行时异常。

try-catch-finally

1
2
3
4
5
6
7
8
9
try{
//运行可能出异常的代码
}catch(SubClassException e){
//如果子类异常类能解决问题,抛出异常。
}catch(ParentClassException e){
//如果子类异常不能处理,交给父类异常处理。
}finally{
//无论有没有抛出异常,最后都运行finally,finally可写可不写
}

示例

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 static void main(String[] args){

try {

int a = 1;
int b = 0;
System.out.println(a/b);
System.out.println("我被执行了吗");

} catch (ArithmeticException e) {

System.out.println("执行子类算数异常:"+e.getMessage());

}catch (NullPointerException e) {

System.out.println("空指针吗?");
}
catch (Exception e) {

System.out.println("执行父类异常:"+e.getMessage());

}finally {

System.out.println("执行了finally");

}
}

从上面的运行结果可以看到,如果try里面的某行代码有异常,那么接下来的代码不会运行,直接进入到catch里。
而且,catch是可以多个使用,因为我们try不可能只写一个代码,可能有多个代码会出现不同的异常。
这catch里的异常怎么写也有讲究,如果是同一级的子类,顺序可以随意,但如果有父类异常,一定要写在子类后面。原因有两,一,子类更能详细异常的问题,二,catch是从上到下执行的,全让父类执行了,那之后的子类也没必要了。

只要写了finally,那它可能就是最后执行的。因为它也会有例外。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args){

int a = 1;
int b = 0;
System.out.println(plus(a,b)); //打印 1

}
public static int plus(int a, int b) {
try {

System.out.println(a/b);
System.out.println("我被执行了吗");

} catch (Exception e) {

return -1;

}finally {

return 1;
}
}

上面这段代码,在plus方法里,catch执行了return -1语句,但并没有结束运行,打印-1。而是继续运行到finally执行return 1.所以最后打印1。所以return也不能阻止finally的运行。但是,看下面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args){

int a = 1;
int b = 0;
try {

System.out.println(a/b);
System.out.println("我被执行了吗");

} catch (Exception e) {

System.out.println("执行catch了吗");
System.exit(0);

}finally {

System.out.println("执行finally了吗");
}

}

而在上面这段代码中,打印“执行catch了吗”,System.exit(0)是直接退出程序。所以没运行到finally。我们写代码要避免使用System.exit(0)的使用。

throws

当然,还有就是甩锅式的抛出异常,我不处理异常,交给上一级处理吧,而上一级可能也不处理异常,也抛了出去,直到抛给了Object类处理异常,它的使用很简单。在方法名后加Throws 和异常名就行。

1
public static void main(String[] args) throws Exception,NullPointerException{}

自定义异常

可能有的时候,异常类里面并没有解决我们的错误,需要我们自己写异常。

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 ThrowableTest {
public static void main(String[] args){

User u = new User();
try {
u.setName("张三");
u.setAge(18);
u.setSex("男");
} catch (MyThrowable e) {
e.printStackTrace();
}
}

}

class MyThrowable extends Exception{
public MyThrowable() {
super();
}
public MyThrowable(String msg){
super(msg);
}
}

class User{
private String name;
private int age;
private String sex;

public void setName(String name) {
this.name = name;
}

public void setAge(int age) throws MyThrowable{
if(age<0) {
throw new MyThrowable("年龄不能为负");
}
else if(age>150) {
throw new MyThrowable("年龄不能超过150岁");
}
this.age = age;
}

public void setSex(String sex) {
this.sex = sex;
}
}

异常以后会常伴在我们左右,所以写代码一定要注意。

谢谢您对我的支持
0%