异常是一种class,Throwable是异常体系的根,继承于Object。Throwable有两个体系:Error和Exception。

  • Error表示严重的错误,程序对此一般无能为力,如:OutOfMemoryError(内存耗尽)、NoClassDefFoundError(无法加载某个Class)、StackOverflowError(栈溢出)等。
  • Exception则是运行时的错误,可以被捕获并处理。分为两类:RuntimeException及子类、非RuntimeException(包含IOException、ReflectiveOperationException等等)。
  • 一些异常是程序逻辑如:NumberFormatException(数据类型的格式错误)、FileNotFoundException(未找到文件)、SocketException(读取网络失败)等。

java规定必须捕获的异常包括Exception及其子类,但不包含RuntimeException及其子类。这类异常称为Checked Exception。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Throwable {
public static void main(String[] args) {
byte[] bs = toGBK("中文");
System.out.println(Arrays.toString(bs));
}

static byte[] toGBK(String str) {
try {
return str.getBytes("GBK");
} catch (UnsupportedEncodingException e) {
UnsupportedEncodingException:
System.out.println(e);
return str.getBytes();
}
}
}

在方法定义时,使用throws表示该方法可能会抛出的异常类型。调用的时候必须强制捕获这些异常,否则编译器会报错。

1
2
3
4
5
6
7
8
9
10
11
12
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Throwable {
public static void main(String[] args) throws UnsupportedEncodingException {
byte[] bt=toGBK("你好");
System.out.println(Arrays.toString(bt));
}
static byte[] toGBK(String str) throws UnsupportedEncodingException {
return str.getBytes("GBK");
}
}

捕获异常

用多个catch语句,每个catch分别捕获对应的Exception及其子类。子类的catch必须写在父类catch前面,要不然会被父类捕获。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Throwable {
public static void main(String[] args) {
try {
byte[] bt = toGBK("你好");
System.out.println(Arrays.toString(bt));
} catch (UnsupportedEncodingException e) {
System.out.println("编码不支持");
} catch (IOException e) {
System.out.println("IO异常");
}
}
static byte[] toGBK(String str) throws UnsupportedEncodingException {
return str.getBytes("GBK");
}
}

当有无论是否发生异常都要执行的代码时,可以用finally语句保证执行,避免多写重复代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Throwable {
public static void main(String[] args) {
try {
byte[] bt = toGBK("你好");
System.out.println(Arrays.toString(bt));
} catch (UnsupportedEncodingException e) {
System.out.println("编码不支持");
} catch (IOException e) {
System.out.println("IO异常");
}finally {
System.out.println("不管你有没有报错,我都要输出");
}
}
static byte[] toGBK(String str) throws UnsupportedEncodingException {
return str.getBytes("GBK");
}
}

某些情况下,可以没有catch,只用try...finally结构。

遇到处理异常的代码一致的异常时,可以使用|分隔,但两者关系不能是类继承关系。

抛出异常

当某个方法抛出异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法。

新的异常如果直接抛出而不关联原始异常, 才会导致原始异常信息被覆盖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package one;
public class Throwable{
public static void main(String[] ages){
try{
fun2();
}catch(Exception e){
e.printStackTrace();
}
}
static void fun1(int a){
if(a==0){
throw new NumberFormatException();
}
}
static void fun2(){
try{
fun1(0);
}catch(NumberFormatException e){
throw new IllegalArgumentException();
}
}
}

如果在执行finally分支语句时抛出异常,原本在catch中的准备抛出的异常就会被屏蔽,因为只能抛出一个异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package one;
public class Throwable{
public static void main(String[] ages){
try{
fun1(0);
}catch(Exception e){
throw new NumberFormatException();
}finally{
System.out.println("我先输出");
throw new IllegalArgumentException();
}
}
static void fun1(int a){
if(a==0){
throw new NumberFormatException();
}
}
}

自定义异常

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
package one;
public class Throwable{
public static void main(String[] ages){
try{
Login login=new Login("admin",null);
}catch(LoginException e){
System.out.println(e.getMessage());
}
}
}
class Login{
public Login(String username, String password){
check(username, password);
}
private void check(String username, String password){
if(username==null || password==null){
throw new LoginException("账号或密码不能为空");
}
}
}
class LoginException extends RuntimeException {
public LoginException() {
super();
}
public LoginException(String message) {
super(message);
}
}