java异常及错误解析

 

什么是异常?

(Throwable)简单粗暴一点的解释就是程序中的错误,但是并不是所有的错误都是异常,比如说Error。举个栗子,你写代码的时候写着写着分号被你丢了,这种情况下会怎么样?

报错了吧,这个你要是不去处理直接编译的话会怎么样?

再来举个栗子,这样会怎么?

这不是没有报红吗?应该没事,来编译一下。

重点来了,在第五行爆出了一个Exception。两种都是错误,但是一个会提醒你直接报红,一个不会提醒你,但是编译的时候就会抛出来。那么综上所述,异常就是不能使你正常运行你的程序的或看的见的或看不见的缺陷。正式的说法就是java异常时java提供的一种识别及响应错误的一致性机制。

 

java异常体系

我们都知道java是单继承多实现的,所以我们顺藤摸瓜肯定能解析出异常这一体系的基本架构和层级关系。下面我就贴一下在java中异常一脉的体系架构。

java异常及错误解析_第1张图片

粗制可以划分成这样。Throwable已知的直接子类只有Error和Exception。

 

Error:

看一下API里的解释:"Error是Throwable的子类表示严重的问题,合理的应用程序不应该试图捕获。一个方法不需要在其throws子句中声明Error的Error ,该子类可能在执行方法期间抛出,但未被捕获,因为这些错误是不应该发生的异常条件。 也就是说, Error及其子类被视为未经检查的异常,用于编译时检查异常。"

 

从上api中我们得知以下几点:

1、Error是Throable的子类,表示错误等级为最严重的

2、Error是不应该去捕获的

3、Error以及其子类属于unchecked异常,用于编译时检查

Error的产生:当资源不足、约束失败、或是其它程序无法继续运行的条件发生时,就产生错误。程序本身无法修复这些错误的。

 

Exception:

看下api里的解释:

类异常及其子类是形式Throwable指示合理的应用程序想要捕获的条件。 

 

异常类和任何不是RuntimeException的子类的子类都是检查异常 。 检查的异常需要在方法或构造函数的throws子句中声明,如果它们可以通过执行方法或构造函数抛出,并在方法或构造函数边界之外传播。”

 

从api中的解释可以得出以下几点:

1、Exception可以分为Checked exception和UnChecked exception

2、表示是有程序员导致的错误

3、应该在程序级处理掉(或抛出或捕获)

4、Checked exception:这类异常是我们必须要去捕获的异常,比如io异常,sql异常。我们必须使用catch块去处理。

5、UnChecked exception:也就是我们平时说的runtime exception及其子类。因为总是由虚拟机接管,所以对于这种异常我们可以不去捕获它,当它发生时要么线程终止,要么主程序终止。

 

java中的异常机制的意义

我们知道,java异常机制可以使程序中异常处理代码和正常的业务代码分离,很大程度上提高了代码的健壮性。如果在有效的使用异常的情况下,异常能清晰的回答三个问题,what , where ,why。也就是说异常类型表示抛出了“什么”,异常的堆栈跟踪可以定位“在哪里”抛出,异常信息解释了“为什么”会抛出。

 

throw、throws:

上边提了那么多次的捕获和抛出,那么我们看一下抛出关键字。

首先要知道如果一个方法没有捕获到一个检查性异常,那么该方法就必须使用throws关键字来声明,throws关键字放在方法签名的尾部。举个栗子:

public void study() throws RemoteException{

    throw new RemoteExceotion();

}

由这个栗子我们可以得到以下信息:

throws是用在方法尾部,抛出的是异常类

throw则是明确指出某个地方要抛出这个异常对象

 

try{}catch{}finally{}

说完抛出说捕获吧,捕获也就是说我们需要把可能会抛出的代码放在try{}语句里边,catch{}语句快里打印抛出的异常,finally{}语句里的代码是此方法返回之前必执行的代码。

 

在try、catch、finally块中,若try中有return语句,则返回try中变量的值,不管try块外是否对该变量进行了修改, 都不影响try中return的返回值。若finally中有return语句,则忽略try、catch块中的return语句。 若finally中抛出异常,则整个try-catch-finally块中抛出异常。

 

但是建议大家尽量在try或者catch中使用return语句,通过finally快中达到对try或者catch返回值的修改是不可行的。finally块中避免使用return语句,因为finally快中如果使用return语句会显示的消化掉try、catch块中的异常信息, 屏蔽了错误的发生。finally块中皮面再次抛出异常,否则整个try-catch-finally块的方法抛出异常,并会消化掉try、catch块中的异常。

 

try-catch-finally详解

//---------------------------------

public class Test {
    public static void main(String  args[]){
        //System.out.print("没事就想学java");
        //--------------------
        //int a=(261*2-2)/0;
        //System.out.print(a);
        //Error error;
        System.out.println("test"+test());
        System.out.println("test1"+test1());
        System.out.println("test2"+test2());
        System.out.println("test3"+test3());
    }

    //---------------
    public static String test() {
        String str = "";
        try {
            str = "try---每天学java";
            return str;//try里边直接返回str
        } catch (Exception e) {
            str = "catch";
            return str;
        } finally {
            str = "finally";
        }
    }
    //---------------
    public static String test1() {
        String str = "";
        try {
            str = "try";
            return str;
        } catch (Exception e) {
            str = "catch";
            return str;
        } finally {
            str = "finally";
            return str;//finally里边直接返回str消化掉try-catch里的str信息
        }
    }

    //----------------
    public static String test2() {
        String str = "";
        try {
            str = "try";
            Integer.parseInt(null);
            return str;
        } catch (Exception e) {
            str = "catch";
            return str;//try里边产生异常catch直接返回str
        } finally {
            str = "finally";
        }
    }
    //--------------------
    public static String test3() {
        String str = "";
        try {
            str = "try";
            Integer.parseInt(null);//产生异常
        } catch (Exception e) {
            str = "catch";
            return str;//捕获到异常信息
        } finally {
            str = "finally";
            return str;//最终被finally里的return消化掉
        }
    }
}

//---------------------------------

finally语句中的return语句显示消化try-catch里的信息

java异常及错误解析_第2张图片

结果图

java异常及错误解析_第3张图片

总结:对于异常我们就说这么多,主要是抛出和捕获,那么定会有人问,当遇到异常的时候是抛出好呢还是捕获好呢?对于这个问题我只能说看完下面的分析后后你自回答吧。一般来说,GUI端是要处理异常的,比如JSP捕获到异常之后,需要先是给用户一个友好的出错信息,而不要给出系统的出错信息。系统的出错信息一方面不太友好,另一方面提供了太多的系统信息,容易被恶意用户用来攻击系统。

换句话说,所有的异常最终必须有一个终极的处理者,这就是GUI。至于中间的环节,比如在服务器端运行的JavaBean是否要处理捕获到的异常,还是继续抛出所捕获的异常,需要视具体情况处理。   

除非你想把异常处理的责任交给调用者,一般不用throws。 比如你要读入一些文件,如果你想通知调用者,让调用者决定如何处理这个异常,你就把这个异常throws给调用者;如果你知道应该如何处理这个异常,或者你想把异常马上解决,你可以就地catch它。 当然,如果catch了还是有问题那么你就只能去调试它,只能看日志信息了。

这完全取决于你想把异常自己立即处理还是想把处理责任返回给调用者。取决于你的程序的结构和要求。   
需要注意的有:
1、如果无法处理某个异常,那就不要捕获它。   
2、如果捕获了一个异常,请不要胡乱的处理它。   
3、尽量在靠近异常被抛出的地方捕获异常。   
4、在捕获异常的地方将它记录到日志中,除非您打算将它重新抛出。   
 

https://mp.weixin.qq.com/s?__biz=MzU0MDg1MzQzNA==&tempkey=OTcxXzZFc3FjSzVjNDdoZ3VoRjN2ZEpsLUtBZ1hIbHFxVEJLU1RvMFdZd01WQlRiVFZQWTVyS0puQ1AtYk5VWWwyaDlJSXNMT0QzbGZXck9FLTNUd0hUUDVrVlRwZmphOEtxNm52NzRXbkNYT1gzWDYySUFHMXB2OFRoc2dQWU1SeFBiYk4ySEJabGJWc1hyMWlqREpYOGdhUGV1TmtaUWVjM0JUS1JsY0F%2Bfg%3D%3D&chksm=7b3397764c441e608dafc1347ba22617538f209b958eab5dadb1a1d6d3f7ac133121a2f43f33#rd

更多内容请前往公众号“每天学Java”  免费资源、工具等你get ,“每天学java”微信小程序已经上线,题库,文章等你来搞事情哦

你可能感兴趣的:(java异常及错误解析)