关于java:聊聊Java的异常机制问题

32次阅读

共计 2818 个字符,预计需要花费 8 分钟才能阅读完成。

摘要:java 异样指在程序运行时可能呈现的一些谬误,如:文件找不到、网络连接失败、非法参数等。异样是一个事件,它产生在程序运行期间,中断了正在执行的程序的失常指令流。

本文分享自华为云社区《Java 知识点问题精选之异样机制》,原文作者:breakDraw。

java 异样指在程序运行时可能呈现的一些谬误,如:文件找不到、网络连接失败、非法参数等。异样是一个事件,它产生在程序运行期间,中断了正在执行的程序的失常指令流。

Java 通过 API 中 Throwable 类的泛滥子类形容各种不同的异样。因此,Java 异样都是对象,是 Throwable 子类的实例,形容了呈现在一段编码中的谬误条件。当条件生成时,谬误将引发异样。对于运行时异样、谬误或可查异样,Java 技术所要求的异样解决形式有所不同。

异样体系分类

Q:Throwable 和 Error 的关系
A:Throwable 是 Error(谬误)的基类,也是 Exception 的基类
1 个好图,可看到常见的异样和 error

Q:Error 和 Exception 的关系
A:

  • Error 个别是会间接引起 jvm 出错的谬误,例如 Java 虚拟机运行谬误等,如果呈现了以后线程会无奈持续运行。
  • Excpetion 是程序自身能够解决的异样。产生后还能失常运行。

Q:Error 能够被 catch 捕获吗?
A:只有是 Throwable 和其子类都是能够 throw 和 catch 的。然而不倡议捕获 Error。

异样体系还能够分为这 2 类:

  • unchecked exception(非查看异样)
    也称运行时异样(RuntimeException),比方常见的 NullPointerException、IndexOutOfBoundsException。对于运行时异样,java 编译器不要求必须进行异样捕捉解决或者抛出申明,由程序员自行决定。
  • checked exception(查看异样,编译异样)
    也称非运行时异样(运行时异样以外的异样就是非运行时异样),java 编译器强制程序员必须进行捕捉解决,比方常见的 IOExeption 和 SQLException。对于非运行时异样如果不进行捕捉或者抛出申明解决,编译都不会通过。

异样捕获和返回

Q:return-finally 陷阱 1:finally 能通过批改变量,来更新 return 的变量值吗

int f() {
  int a = 1;
  try {return a;}
  finally {a=2;}
}

A: 不能,f 返回 1。

Q:return-finally 陷阱 2:finally 里也 return 时,返回哪个?

int f() {
  try {return 1;}
  finally {return 2;}
}

A:返回 finally 里的,返回 2。

Q:什么状况下 finally 块里的步骤能够不执行?
A:只有在 finally 之前调用 System.exit(0) 退出 jvm,能力让 finally 不执行。

Q:上面会产生什么?

try {start();
} catch (Exception ex) {System.out.println("catch Exception");
} catch (RuntimeException re) {System.out.println("catch RuntimeException");
}

A: 间接编译就谬误了。catch 是会按程序的且匹配 1 个就不再往下匹配,编译器因而辨认出 RuntimeExcpetion 永远不会被捕捉到,便提前报错。

Q:throw 异样的时候,在 finally 中做 return,那么异样还会抛出吗?

static int f() {
    try {
        int a = 1/0;
        return a;
    } catch (Exception e) {throw new RuntimeException(e);
    } finally {return -1;}
}
public static void main(String[] args) {System.out.println(f());
}

A: 不会,返回 -1.

即 finaly 中做 return 会中断 throw
因而永远不要在 finally 中去做 return 操作

受检异样相干问题

Q: 子类覆写基类办法时,能 throws 基类办法中不存在的异样吗?
像上面这样:

class A{void f() throws IOException{}}
class B extends A{void f() throws IOException, SQLException {}}

A: 不行,间接编译报错。即子类覆写父类办法时,throws 关键字前面跟的异样必须是小于等于父类办法异样的。

Q: finally 中调用某资源的 close 时,也会抛出受检异样,除了在 finally 里做 try-catch,还能怎么做?

像上面这样,finally 又有 catch,就很难看:

TryWithResource tryWithResource = new TryWithResource();
        try {System.out.println(tryWithResource.age);
        } catch (Exception e) {e.printStackTrace();
        }finally {
            try {tryWithResource.close();
            } catch (Exception e) {e.printStackTrace();
            }
        }

A:如果是 JDK1.7,能够用 try-with-resource 语法。

须要资源类实现 AutoCloseable 接口,并在 try 的时候在 try 括号前面跟上资源的创立,如下:

 public static void main(String[] args) {try (TryWithResource tryWithResource = new TryWithResource()) {System.out.println(tryWithResource.age);
        } catch (Exception e) {e.printStackTrace();
        }
    }

这样就不须要写 finally,finally+close 会通过编译器给咱们主动加上。

Q: 线程抛出异样的话该怎么捕获?

A:实现异样解决接口 MyUnchecckedExceptionhandler

public class MyUnchecckedExceptionhandler implements UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {System.out.println("捕捉异样解决办法:" + e);
    }
}

而后把实现类设置给对应线程。

Thread t = new Thread(new ExceptionThread());
t.setUncaughtExceptionHandler(new MyUnchecckedExceptionhandler());
t.start();

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0