Java中的异常

Posted 张同学吧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中的异常相关的知识,希望对你有一定的参考价值。

初识异常

在我们之前遇到的代码中,多多少少都会有报错的情况,就比如:数组越界、除数为0、指针为空等情况。所谓异常指的就是程序在 运行时 出现错误时通知调用者的一种机制。
和编译期的错误不一样,编译时出错一般是指拼写错误,语法错误。而运行时指的是程序已经编译通过了,得到了class文件再由JVM执行过程中出现的错误。

异常的基本用法

基本语法

使用 try 和 catch 关键字可以捕获异常,try/catch代码块中的代码称为保护代码,可以放在异常可能发生的地方,具体用法如下:

try
{
   //有可能出错的程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}finally {
	异常的出口
}
try 代码块中放的是可能出现异常的代码.
catch语句包含要捕获异常类型的声明。catch 代码块中放的是出现异常后的处理行为.
finally 代码块中的代码用于处理善后工作, 会在最后执行.
其中 catch 和 finally 都可以根据情况选择加或者不加.

基本用法

1.使用try catch捕捉异常

int[] arr = {1, 2, 3};
try {
	System.out.println("before");
	System.out.println(arr[100]);
	System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
	// 打印出现异常的调用栈
	e.printStackTrace();
}
System.out.println("after try catch");
// 执行结果
before
java.lang.ArrayIndexOutOfBoundsException: 100
	at demo02.Test.main(Test.java:10)
after try catch

当保护代码块中发生一个异常时,那么 try 代码块中的程序就不会继续执行, 而是交给 catch 中的代码来执行. catch执行完毕会继续往下执行.。

2.catch 只能处理对应种类的异常
比如:

int[] arr = {1, 2, 3};

try {
	System.out.println("before");
	arr = null;
	System.out.println(arr[100]);
	System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
	e.printStackTrace();
}
System.out.println("after try catch");

这段程序代码的执行结果会仍然报错,因为catch所捕捉的错误类型与try中的错误类型不匹配,所以没有捕捉到。
3.**catch可以有多个**
例如

```java
catch (ArrayIndexOutOfBoundsException e) {
	System.out.println("这是个数组下标越界异常");
	e.printStackTrace();
} catch (NullPointerException e) {
System.out.println("这是个空指针异常");
	e.printStackTrace();
}
/*一段代码可能会抛出多种不同的异常, 不同的异常有不同的处理方式. 因此可以搭配多个 catch 代码块.
如果多个异常的处理方式是完全相同, 也可以写成这样*/
catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
	...
}

由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。也可以进行多重捕获,具体用法是在try代码块后面跟随多个catch代码块。
4.finally 表示最后的善后工作, 例如释放资源
catch 语句往往是和finally配合使用,finally关键字用来创建在try代码块后面执行的代码块,无论是否发生异常,finally代码块中的代码总会被执行,因此,在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
但你也可以在try中就直接回收资源:

try (Scanner sc = new Scanner(System.in)) {
	int num = sc.nextInt();
	System.out.println("num = " + num);
} catch (Exception e) {
	e.printStackTrace();
}

这样一来scanner。close会直接在try执行完毕后自动调用。
5.如果本方法中没有合适的处理异常的方式, 就会沿着调用栈向上传递,如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止

java异常体系

  • 顶层类 Throwable 派生出两个重要的子类, Error 和 Exception
  • 其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现.
  • Exception 是我们程序猿所使用的异常类的父类.
  • 其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类
  • NullPointerException , IndexOutOfBoundsException 等.
  • Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为受查异常

自定义类异常

Java 中虽然已经内置了丰富的异常类, 但是我们实际场景中可能还有一些情况需要我们对异常类进行扩展, 创建符合
我们实际情况的异常

public static void main(String[] args) {
	try {
		login("admin", "123456");
	} catch (UserError userError) {
		userError.printStackTrace();
	} catch (PasswordError passwordError) {
		passwordError.printStackTrace();
	}
}
public static void login(String userName, String password) throws UserError,PasswordError {
	if (!Test.userName.equals(userName)) {
		throw new UserError("用户名错误");
	}
	if (!Test.password.equals(password)) {
		throw new PasswordError("密码错误");
	}
	System.out.println("登陆成功");
}

小tips:

在这里我用到了throws,throws和throw的区别在于:
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:(修饰符)(方法名)([参数列表])[throws(异常类)]{…}
例:public void doA(int a) throws Exception1,Exception3{…}
throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。
throws语句用在方法声明后面,主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常。如果再抛出异常,由该方法的调用者来处理。
throw是具体向外抛异常的动作,所以它是抛出一个异常实例。

所以throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常

以上是关于Java中的异常的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.NullPointerException: Attempt to invoke virtual method ‘int android.database.sqlite异常(代码片段

片段中的Android致命异常

异常和TCP通讯

片段中的getView()导致抛出异常,不确定原因

java 反射代码片段

片段中的空指针异常