赞
踩
目录
case5:也可以用一个catch捕获所有异常(不推荐这样写)
case7:使用try负责回收资源(finally回收资源的等价写法)
case8:如果本方法中没有合适的处理异常的方式,就会沿着调用栈向上传递。
异常:是指程序在运行时出现错误通知调用者的一种机制。
异常是“运行时”的事情,是代码已经跑起来了出现的异常。这时程序已经编译通过得到class文件了,再由JVM执行过程中出现的错误。
编译:如果代码写错了,比如出现一些语法错误,编译不通过,报的是编译错误,这时代码还没跑起来。
常见的异常:
①除以0
②数组下标越界
③访问null对象
Java内置了丰富的异常体系,用来表示不同情况下的异常。下图表示Java内置的异常类之间的继承关系:
顶层类Throwable派生出两个重要的子类,Error和Exception。
其中 Error 指的是 Java 运行时内部错误和资源耗尽错误. 应用程序不抛出此类异常. 这种内部错误一旦出现,除了告知用户并使程序终止之外, 再无能无力. 这种情况很少出现.
Exception 是异常类的父类,其中 Exception 有一个子类称为 RuntimeException , 这里面又派生出很多我们常见的异常类NullPointerException , IndexOutOfBoundsException 等
Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查异常, 所有的其他异常称为受查异常.
如果一段代码可能抛出受查异常, 那么必须显式进行处理。显式处理的方式有两种:
a) 使用 try catch 包裹起来
b) 在方法上加上异常说明, 相当于将处理动作交给上级调用者
错误在代码中是客观存在的,因此需要让程序出现问题的时候及时通知程序员。有两种方式:
LBYL:在操作之前就做充分的检查。
EAFP:“事后获取原谅比事前获取许可更加容易”,先操作,遇到问题再处理。
try代码块中放的是可能出现异常的代码。
catch代码中放的是出现异常后的处理行为。
finally代码块中的代码处理善后工作,会在最后执行。
catch和finally都可以根据情况选择加或者不加。
- public static void main(String[] args) {
- int[] array = {1,2,4};
- try{
- System.out.println("aaa");
- System.out.println(args[100]);
- System.out.println("bbb");
- }catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace(); // 打印出异常的调用栈
- }
- System.out.println("我不是try里面的内容哦");
- }
一旦try中出现异常,那么try代码块中的代码就不会继续执行,而是交给catch中的代码来执行。catch执行完毕后会继续往下执行。
- public static void main(String[] args) {
- int[] array = {1,2,4};
- try{
- System.out.println("aaa");
- System.out.println(args[100]);
- System.out.println("bbb");
- }catch (ArithmeticException e){
- e.printStackTrace(); // 打印出异常的调用栈
- }
- System.out.println("我不是try里面的内容哦");
- }
异常不匹配,catch并不能捕获到数组越界异常。
一段代码可能会抛出多种不同的异常,不同的异常有不同的处理方式,因此可以搭配多个catch代码。
- // 写法1
- public static void main(String[] args) {
- int[] array = {1,2,4};
- try{
- System.out.println("aaa");
- System.out.println(args[100]);
- System.out.println("bbb");
- }catch (ArithmeticException e){
- e.printStackTrace(); // 打印出异常的调用栈
- }catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace();
- }
- System.out.println("我不是try里面的内容哦");
- }
- // 写法2
- // 如果多个异常的处理方式完全相同,也可以这样写
- public static void main(String[] args) {
- int[] array = {1,2,4};
- try{
- System.out.println("aaa");
- System.out.println(args[100]);
- System.out.println("bbb");
- }catch (ArithmeticException | ArrayIndexOutOfBoundsException e){
- e.printStackTrace(); // 打印出异常的调用栈
- }
- System.out.println("我不是try里面的内容哦");
- }
Exception类是所有异常类的父类,因此可以用这个类型来捕获所有异常。
- public static void main(String[] args) {
- int[] array = {1,2,4};
- try{
- System.out.println("aaa");
- System.out.println(args[100]);
- System.out.println("bbb");
- }catch (Exception e){
- e.printStackTrace(); // 打印出异常的调用栈
- }
- System.out.println("我不是try里面的内容哦");
- }
- public static void main(String[] args) {
- Scanner scanner = new Scanner(System.in);
- try{
- int a = scanner.nextInt();
- System.out.println(a);
- }catch (InputMismatchException e){
- e.printStackTrace();
- }finally {
- scanner.close();
- }
- }
无论是否存在异常,finally中的代码一定都会执行到。保证最终一定会执行到Scanner的close方法。
- public static void main(String[] args) {
- try (Scanner scanner = new Scanner(System.in)) {
- int a = scanner.nextInt();
- System.out.println(a);
- } catch (InputMismatchException e) {
- e.printStackTrace();
- }
- }
try上有一个加深底色,这是IDEA针对我们的代码提出了一些更好的建议。鼠标在try上停留,按住ctrl+enter,会弹出一个改进方案的弹窗,选择后,代码自动调整为如下代码
- public static void main(String[] args) {
- try{
- func();
- }catch (ArrayIndexOutOfBoundsException e){
- e.printStackTrace();
- }
- System.out.println("我在trycatch的后面");
- }
- public static void func(){
- int[] elem = {1,2,3};
- System.out.println(elem[100]);
- }
注意:如果向上一直传递都没有合适的方法处理异常,最终就会交给JVM处理,程序就会异常终止。
程序先执行try中的代码。
如果try中的代码出现异常,就会结束try中的代码,看出现的异常和catch中的异常类型是否匹配。
如果找到匹配的异常类型,就会执行catch中的代码。
如果没有找到匹配的异常类型,就会将异常向上传递给上层调用者。
无论是否找到匹配的异常类型,finally中的代码都会被执行到。
如果上层调用者也没有处理异常,就继续向上传递。
一直到main方法也没有合适的代码处理异常,就会交给JVM来进行处理,此时程序就会异常终止。
程序员可以利用throw,手动的抛出某个异常。
- public static void main(String[] args) {
- int x = 0;
- if (x == 0) {
- throw new RuntimeException("抛出异常");
- }
- }
在处理异常的时候,通常希望知道这段代码中可能出现哪些异常。可以使用throws关键字,把可能抛出的异常显示的标注在方法定义的位置,提醒调用者要注意捕获这些异常。
- public static int divide(int x,int y) throws ArithmeticException{
- if(y == 0){
- throw new ArithmeticException("除数为0哦");
- }
- return x/y;
- }
finally中的代码保证一定会执行到,这也会带来一些麻烦。
- public static void main(String[] args) {
- System.out.println(func()); // 20
- }
- public static int func(){
- try{
- return 10;
- }finally {
- return 20;
- }
- }
①finally中没有return,try和catch中有return,先执行finally,再return;
②如果finally中也有return,就会执行finally中的return,从而不会执行到try中原有的return。
一般不建议在finally中写return。
- class UserError extends Exception{
- public UserError(String message){
- super(message);
- }
- }
- class PasswordError extends Exception{
- public PasswordError(String message){
- super(message);
- }
- }
- public class TestDemp6 {
- public static String username = "admin";
- public static String password = "1111";
- public static void login(String name,String password) throws UserError,PasswordError{
- if(!username.equals(name)){
- throw new UserError("用户名错误");
- }
- if(!username.equals(password)){
- throw new PasswordError("密码错误");
- }
- }
- public static void main(String[] args) {
- try{
- login("zhangsan","1111");
- }catch (UserError userError){
- userError.printStackTrace();
- }catch (PasswordError passwordError){
- passwordError.printStackTrace();
- }
- }
- }
注意事项:
自定义异常通常会继承自Exception或者RuntimeException
继承自Exception的异常默认是受查异常
继承自RuntimeException的异常默认是非受查异常。
异常的处理:使用try-catch包裹、加上声明(throws)交给上层调用者处理。
当出现异常后,try里面的内容不再继续执行,程序接着往下执行。
catch需要捕获对应的异常才能处理异常,也能有多个catch语句。
finally最后都会被执行到。不建议在finally里面写return。
catch和finally都是可有可无的。
受查异常必须被显示的处理。
不建议使用catch捕获Exception。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。