java异常处理

java基础-异常处理


发现错误的理想时机是在编译阶段,但编译器并不能在编译器找出全部的异常,余下的异常必须在运行期间解决。异常处理是java中唯一正式的错误报告机制,并且通过编译器强制执行。
Alt text

捕获异常

java支持终止模型,在这种模型中,一旦异常被抛出,就表明错误已经无法挽回,不能回来继续执行代码。
####try-catch异常

try{
     //try块中放可能发生异常的代码。
}catch(IOException IOexception){
    //处理对应的异常
}catch(SQLException SQLexception){
    //...
}finally{
    //无论异常是否发生,异常是否匹配被处理,finally都会执行。
    //一个try至少要有一个catch块,至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。
    //finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。 
}

每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的,只有第一个匹配的catch会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义。
####自定义异常
要自己定义异常类,必须从已有的异常类中继承

//create your own exceptions

class SimpleException extends Exception{}

public class InheritingExceptions{
	public void f() throws SimpleException {
		System.out.println("SimpleException from f()");
		throw new SimpleException();
	}
	public static void main(String[] args){
		InheritingExceptions sed = new InheritingExceptions();
		try{
			sed.f();
		}catch(SimpleException e){
			System.out.println("caught it");
		}
	}
}

抛出异常

throws:仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。
注意:Java程序可以是多线程的。每一个线程都是一个独立的执行流,独立的函数调用栈。如果程序只有一个线程,那么没有被任何代码处理的异常 会导致程序终止。如果是多线程的,那么没有被任何代码处理的异常仅仅会导致异常所在的线程结束。
###异常与记录日志

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;

public class LoggingExceptions2 {

    private static Logger logger = Logger.getLogger("LoggingExceptions2");
    static void logException(Exception e){
        StringWriter trace = new StringWriter();
        e.printStackTrace(new PrintWriter(trace));
        logger.severe(trace.toString());
    }
    
    public static void main(String[] args) {
        try {
            throw new NullPointerException();
        } catch (NullPointerException e) {
            logException(e);
        }
    }
}

Alt text
###异常链
想要在捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下来,这称为异常链。这项技术主要是异常类的一个Throwable的子类函数来实现的,接收的参数的异常,我们叫他根源异常(cause)。

public class Throwable implements Serializable {
    private Throwable cause = this;
   
    public Throwable(String message, Throwable cause) {
        fillInStackTrace();
        detailMessage = message;
        this.cause = cause;
    }
     public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }
    
    //........
}

在Throwable的子类中,只有Error,Exception,RuntimeException提供了带cause参数的构造器。如果要把其他类型的异常连接起来,应该使用initCause()方法。
###finally清理
1.在try块中即便有return,break,continue等改变执行流的语句,finally也会执行。

public class Test1 {
    public static void main(String[] args){
        int re = bar();
        System.out.println(re);
    }
    private static int bar(){
        try{
            return 5;
        } finally{
            System.out.println("finally");
        }
    }
}

Alt text

2.finally 中的 return 会覆盖 try 或者 catch 中的返回值。

public class Test1 {
    public static void main(String[] args) {
        int result;

        result  =  foo();
        System.out.println(result);     /2

        result = bar();
        System.out.println(result);    /2
    }

    @SuppressWarnings("finally")
    public static int foo() {
        try{
        int a = 5 / 0;
        } catch (Exception e){
            return 1;
        } finally{
            return 2;
        }

    }
    @SuppressWarnings("finally")
    public static int bar() {
        try {
            return 1;
        }finally {
            return 2;
        }
    }
}

Alt text

3.finally 中的 return 会覆盖前面 try 或者 catch 块中的异常。
4.finally 中的异常会覆盖前面 try 或者 catch 中的异常。
5.异常丢失:某些特殊的方式使用finally会造成异常丢失。
####在以下4种特殊情况下,finally块不会被执行:
1.在finally语句块中发生了异常。
2.在前面的代码中用了System.exit()退出程序。
3.程序所在的线程死亡。
4.关闭CPU。
###异常使用指南
应该在下列情况下使用异常:
1.在恰当的级别处理问题。(在知道该如何处理的情况下才捕获异常)
2.解决问题并且重新调用产生异常的方法。
3.进行少许修补,然后绕过异常发生的地方继续执行。
4.用别的数据进行计算,以代替方法预计会返回的值。
5.把当前运行环境下能做的事尽量做完,然后把相同的异常重抛到更高层。
6.把当前运行环境下能做的事尽量做完,然后把不同的异常抛到更高层。
7.终止程序。
8.进行简化。
9.让类库和程序更安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值