基本异常
1,先捕获小异常再捕获大异常不然会出现错误!(已捕获异常异常)
2,Java7以前每个cath只能捕获一个异常,在Java7以后能捕获多个异常,异常用 | 分割,多异常捕获时异常有隐式的final修饰,因此不能再对异常赋值**(非多异常捕获可以赋值)**,而且对有父子类关系的异常类不能用多异常捕获,多重捕获中的类型必须是不相交的(还是先处理小异常)
catch (IndexOutOfBoundsException|NumberFormatException exception){
System.out.println("sdf");
}
Java的垃圾回收机制可以回收Java对象,但是不会回收物理资源(数据库链接,网络连接,磁盘文件)所以必要的资源回收是必须的,为了保证能回收好资源Java提供了finally,不管是否出现了异常进入了哪个cath,甚至是在try或者cath执行了 return语句finally也会被执行**(返回操作前被执行)**;
但是System.exit(1)代码是退出虚拟机在fianlly前执行的话也就不能进入fianlly代码块了。
public class A {
public static void main(String[] args) {
System.out.println(f());
}
static int f(){
int i=9;
try {
i=10/0;
i=90;
}catch (RuntimeException exception){
System.out.println("RuntimeException ....");
return i;
}finally {
System.out.println("fianlly....");
}
return 9999;
}
}
结果:
RuntimeException ....
fianlly....
9
在通常情况下不要再fianlly 里面使用return或者throw 语句否则会导致try,catch 语句里面的return,throw语句失效。
当java程序在执行try,catch 语句的时候遇到了return,throw语句的时候会去寻找finally语句块,要是在finally里面使用了return,throw语句的时候会导致执行的是fianlly里面的语句,执行fianlly的return,throw,正常情况下,也就是finally语句里面没有那两个语句的时候,执行完fianlly代码块,然后再去执行try,catch 的return,throw语句。
尽量不要在fianlly里面使用return,throw语句否则很可能出现奇怪的异常
异常处理嵌套
异常处理流可以放在任何可以执行代码的地方,但一般不建议超过两层,避免可读性降低
package cn.lin.feng.Ex;
public class B {
public static void main(String[] args) {
try {
try {
try {
}catch (Exception e){
}
}catch (Exception e){
}
}catch (RuntimeException e){
try {
}catch (Exception e1){
}
}finally {
try {
}catch (Exception e2){
}finally {
}
}
}
}
java7&java9增强的自动关闭的try 语句
try(BufferedReader bufferedReader = new BufferedReader(new FileReader("C.txt"));) {
}
java7
在try里面使用的资源由try(资源声明组成)。里面的资源必须实现auotocloseable或者closeable接口(auotocloseable接口是closeable的子接口)
自动关闭的try()相当于有隐含的finally代码块(这个代码块用来实现关闭资源,自己也可以写finally块)
Java9
java9再次加强了这种try语句java9不要求在()里面申请资源了,只要在()里面声明变量就好,而且里面 的变量必须是final的(变量显式声明为fianl或者是没有显式声明为final但是没有对其再次赋值的,该变量就是有效的fianl)
try(bianlangA;bianlaingB){
}
checked异常和Runtime异常体系
java异常被分为两类:checked异常和Runtime异常
checked异常要求程序员必须注意,要么显示声明抛出要么显示捕获和处理异常总之不能对checked异常总之对其不能不闻不问
throws Exception1,Exception2
使用throws抛出异常有“两小”的规则,不能比父类的异常大,不能比父类的异常多。
throw new Exceptioncalss("message!");
public class D extends Exception{
public D(){}
public D(String message){
super(message);
//这里的message是使用getMessage()的返回值
}
}
一般就是这样定义一个异常类,主要目的是为了让异常类的名字能见名知意
catch和throw同时使用
主要目的是为了避免在方法里面自己处理了异常而方法的调用者不能发现该异常就是为了异常的多方处理。
public static void main(String[] args) throws FileNotFoundException {
/
catch (FileNotFoundException e) {
e=new FileNotFoundException("xxxxxxx");
throw e;
}
用throw抛出异常的时候在java7后可以自动检测可能产生的异常,
public static void main(String[] args) throws FileNotFoundException {
try {
final FileOutputStream f = new FileOutputStream("a.txt");
}catch (Exception e){
throw e;
}
}
这里只要抛出实际的异常就可以了
异常链(23种设计模式之一|职责链模式也叫异常链)
JDK1.4后所有的Throwable的子类在构造器里面都有个
public Exception(Throwable cause) {
super(cause);
}
类似这个的构造器cause就是异常原始信息对应的异常类应该调用父类的该函数
代码示例:
public class E {
public static void main(String[] args) throws IOException {
final E e = new E();
e.test1();
}
public void test1() throws IOException {
test2();
}
private void test2() throws IOException {
test3();
}
private void test3() throws IOException {
try {
throw new D("D类异常!!");
}catch (Exception e){
e.printStackTrace();
final IOException ioException = new IOException("啊哈哈哈哈哈哈!!!");
ioException.initCause(e);
throw ioException;
}
}
}
结果:
cn.lin.feng.Ex.D: D类异常!!
at cn.lin.feng.Ex.E.test3(E.java:20)
at cn.lin.feng.Ex.E.test2(E.java:15)
at cn.lin.feng.Ex.E.test1(E.java:11)
at cn.lin.feng.Ex.E.main(E.java:8)
Exception in thread "main" java.io.IOException: 啊哈哈哈哈哈哈!!!
at cn.lin.feng.Ex.E.test3(E.java:23)
at cn.lin.feng.Ex.E.test2(E.java:15)
at cn.lin.feng.Ex.E.test1(E.java:11)
at cn.lin.feng.Ex.E.main(E.java:8)
Caused by: cn.lin.feng.Ex.D: D类异常!!
at cn.lin.feng.Ex.E.test3(E.java:20)
... 3 more