您的位置:首页 > 职场人生

黑马程序员_Java基础——异常(第1篇)

2014-07-25 14:01 246 查看
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

一、概述

    所谓异常就是程序运行时出现的不正常的情况。我们知道,Java中的所有的东西都是对象,即是所谓的万物皆对象,都属于某一个类,所有的东西也都是从现实生活中而来。关于异常的由来也不例外,问题是现实生活中一个具体的事物,其也可以通过Java的类的形式来描述,并封装成对象,所以,异常就是Java对不正常的情况进行描述后的对象的体现。

    异常也有严密的体系,最上层的基类为Throwable,下面两个子类分别为Error和Exception。对于这两个子类也是有些分别,Error在Java文档中的描述为用于指示合理的应用程序不应该视图捕获的严重问题,也就是说当程序抛出了Error以及其子类异常的话,我们不应该去捕获他,因为其是严重的错误,是没有必要进行处理的。因而,我们学习异常的重点就在Exception上,Exception指出了合理的应用程序想要捕获的条件。异常的子类众多,这里我们选几个重点的来学习,下面示意图能够更加直观的观察异常体系。



二、简介

    异常既然也是Java中的类,但是其能单独成一个体系,说明了其拥有特殊性。异常体系的特殊性在于,其体系中的所有类以及根据类建立的对象都具备可抛性,可以被throws和throw关键字操作,在Java中只有异常体系具备这个特点。

    那么Java中如何来抛异常呢?抛异常的关键字用throw(s),throw(s)的英文字面意思为抛、可抛的,那么thorw和throws的区别在哪里?首先,throws用在函数上,而throw用在函数内,其次,throws后面跟的是异常类,而且可以抛出多个异常类(用逗号隔开),而throw后面跟的是异常对象。

    在Java中我们使用try{}catch(){}finally{}这种方式来处理异常。

//异常的处理基本流程为

try
{
//需要被检测的代码
}
catch (异常类 变量)
{
//处理异常的的代码
}
finally
{
//一定会执行的语句
}


         对于可能有异常的代码我们需要用try块来捕获异常,将捕获到的异常交给catch块来处理,对于必须要执行的代码可以放在finally块中。除了捕获异常,也可以在函数上将异常类或者在函数内部把异常对象抛出去,给调用者进行处理。调用到抛出异常的功能时,抛几个异常就处理几个异常,一个try块可以对应多个catch块,如果有父类的异常,则需要将父类的catch块放在最下面,因为其接受异常是从上到下执行的,如果父类的catch块在上面就会接受子类的异常,那么下面的catch块就都没用了。再说catch块中的处理需要进行针对性的处理,而不是简单的打印消息,更不能不写。catch块中的处理代码,如果在本功能处理不了时可以继续在catch块中抛出,或者异常虽然可以处理,但需要将异常产生的和本功能相关的问题提供出去,让调用者知道或处理,或者将异常转换为调用者能处理的异常抛出去。当函数内容抛出异常对象,而且并未try处理的时候,此时必须要在函数上声明,否则编译失败。当然RutimeException运行时异常除外。对于调用了声明了异常的函数时,调用者可tyr可抛,根据具体情况决定。

//多异常的处理流程

int div(int a, int b)throws ArithmeticException, ArrayIndexOutOfBoundsException
{
...
}
public static void main(String[] args)
{
try
{
//...
}
catch (ArithmeticException e)
{
}
catch(ArrayIndexOutOfBoundsException e)
{
}
}
//如果有父类异常,则要放在最下面

三、自定义异常以及异常类的继承等等

    根据编译器的设定,异常有两种。一种为编译时被检测的异常,比如异常在编译时没有被处理(没有抛或者try),则会编译失败。另一种为运行时异常,也就是说编译时不检测不处理,这种异常就是Exception下的RuntimeException异常,这是非常特殊的一个类。如果在函数内抛出此异常,函数上不声明一样可以编译通过。之所以不需要声明,是因为不需要让调用者去处理,当该异常发生时,希望程序停止,是因为在运行时出现了无法继续执行下去的情况,希望程序停止,修正代码。在函数上抛出此异常同样可以不处理。

    当在程序中出现我们所特有的问题时,Java提供的异常类无法满足我们的需求,此时,我们就需要自定义异常。按照Java面向对象的思想,将程序中出现的特有问题进行封装,就是我们所需要的自定义异常。具体步骤为,定义类继承Exception或者RuntimeException——让自定义类具备可抛性和异常操作的共性方法。

//当自定义异常信息时,可以使用父类已经定义好的功能,异常信息传递给父类的构造函数。

class MyException extends Exception
{
MyException(String msg)
{
super(msg);
}
}

//自定义异常的小例子

class FuShuException extends Exception
{
/*
private String msg;
FuShuException(String msg)
{
this.msg = msg;
}
public String getMessage()
{
return msg;
}
//其实,这里在throwable中已经这么做过了,在throwable中有一个构造函数为Throwable(String message)...
//所以在Exception中,也有这么一个构造函数Exception(String msg){super(msg));},不过其实现是用super(msg)调用的Throwable中的构造函数实现的,所以在自定义的异常时只需要调用Exception的构造函数就行了super(msg
)
*/
FuShuException(String msg)
{
super(msg);
}
}
class Demo
{
int div(int a, int b)throws FuShuException
{
if(b < 0)
throw new FuShuException("/负数");  //自定义的异常需要手动throw抛出
//当函数内部出现throw抛出异常对象,那么就必须处理,要么在内部tyr catch处理,要么throws抛出给调用者
return a/b;
}
}
class FuShuExceptionDemo
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int x = d.div(4, -1);
System.out.println("x = " + x);
}
catch (FuShuException e)
{
System.out.println("除数为负数了");
System.out.println(e.toString());//这里toString方法自动调用的是getMessage方法,只要在初始化的时候给入值就可以了
}
}
}
    异常中的方法在子父类覆盖中也显得很有意思。首先,如果父类的方法抛出异常,那么覆盖的子类覆写其中的方法只能抛出父类的方法中抛出的异常或者是那些异常的子集。如果父类方法没有抛出异常,那么子类方法也就不能把异常抛出去,只能try处理,在函数内部就处理掉。

    finally块中存放的是一定会被执行的代码,比如:关闭资源(数据库连接)的动作就需要放在finally中,一般在对数据库的操作中,SQLException异常不抛,而是捕捉处理,一般处理之后抛出一个用户能够处理的异常。

//一般finally中就是关闭资源的情况最为常见,而关闭数据库的操作更为常见,对数据库异常的操作,如下:

public void method()throws NoException
{
/*
连接数据库
数据操作    throw new SQLException();
关闭数据库  该动作无论数据库是否操作成功,都要执行
*/
try
{
连接数据库
数据操作    //抛数据库异常 throw new SQLException();
}
catch (SQLException e)
{
会对数据库进行异常处理
throw new NoException();
}
finally
{
关闭数据库
}
}
四、总结

    try catch finally的组合方式

--try{}catch{}

--try{}catch{}finally{}

--try{}finally{} 没有catch就是没有处理捕捉到的异常

那么有同学可能会有疑问,那就是try{}finally{}什么时候能用到呢?其实finally中还是关闭资源,try块中的内容可以给调用者去处理,但是资源还是要关的,这时候就用到try{}finally{}了

注:finally块中只有一种情况读不到,那就是遇到System.exit(0);时,退出jvm

    综上所述,异常的好处有两点:一是将问题进行封装,二是将正常流程代码和问题处理代码分离,便于阅读。

  

    

----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: