您的位置:首页 > 编程语言 > Java开发

Java基础_异常

2014-05-13 10:21 155 查看
异常就是程序在运行时出现的不正常情况

异常的由来

问题也是现实生活中具体得事物,也可以通过java的类的形式进行描述,并封装成对象。其实就是java对不正常情况进行描述后的对象体现

无论Error或者Exception都具有一些共性内容

比如:不正常情况的信息,引发的原因等。

异常的体系

Throwable

|--Error

|--Exception

Throwable

Error

通常出现重大问题,如运行的类不存在或者内存溢出等

不编写针对代码进行处理

Exception

在运行时出现的一些非严重问题,可以通过try catch finally处理

Exception和Error的子类名都是以父类名作为后缀

异常的处理

java提供了特有的语句进行处理

try
{
需要被检测的代码;//注意代码的可执行性
}
catch(异常类 变量)//参数用于接收被检测到的异常对象
{
处理异常的代码;(处理方式)
}
finally
{
一定会执行的语句;
}

对捕获到的异常对象进行常见方法操作

String getMessage();//获取异常信息

String toString();//异常名称:异常信息

printStackTrace();//异常名称,异常信息,异常出现的位置

其实jvm默认的异常处理机制就是在调用printStackTrace方法,打印异常在堆栈中的跟踪信息

编写功能的人在函数上通过throws的关键字声明了该功能有可能会出现问题,将问题告诉给调用者,必须处理(要么捕捉try,要么继续抛出throws,最终可由主函数抛出给虚拟机),不然编译失败

int div(int a, int b) throws Exception
{
return a/b;
}

多异常的处理

对多异常的处理,不能同时发生,因为函数中只要有异常发生,该程序就结束了

1、声明异常时,建议声明更为具体的异常,这样处理的可以更具体

2、对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。有多个catch块,会找匹配的第一个catch块

建议在进行catch处理时,catch中一定要定义具体处理方式(一般会记录到一个异常日志文件),不要简单地定义一句e.printStackTrace(),也不要简单的书写一条输出语句。

自定义异常

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象,所以对于这些特有的问题可以按照java的对问题封装的思想将特有的问题进行自定义的异常封装

throw new FuShuException();//手动通过throw关键字抛出一个自定义异常对象,对象的类自定义,并继承Exception

当在函数内部出现了throw抛出异常对象,那么就必须给出对应的处理动作。要么在内部try catch处理,要么在函数上声明让调用者处理。

一般情况下(注意RuntimeException类),函数内出现异常,函数上需要声明。

如何定义异常信息?

因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时将异常信息传递给父类,通过super语句,那么就可以直接通过getMessage方法获取自定义的异常信息了。比如super(message);

自定义异常必须是自定义类继承Exception

继承Exception原因:异常体系有一个特点,因为异常类和异常对象都需要被抛出。他们都具备可抛性。这个可抛性是throwable体系中的独有特点。只有这个体系中的类和对象才可以被throws和throw操作

代码示例:

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

class Demo
{
int div(int a,int b) throws FuShuException
{
if(b<0)
throw new FuShuException("除数为负数");
return a/b;
}
}

class  ExceptionDemo5
{
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(e.toString());
return;
//System.exit(0);//系统,退出。jvm结束。
}
finally
{
System.out.println("finally");//finally中存放的是一定会被执行的代码。
}
System.out.println("over");
}
}


throws和throw的区别:

throws使用在函数上

throw使用在函数内

throws后面跟的是异常类,可以跟多个,用逗号隔开

throw后面跟的是异常对象

RuntimeException

一个特殊的子类异常

如果在函数内抛出该异常,函数上可以不用声明,编译一样通过

如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过

之所以不用在函数上声明是因为不需要让调用者处理。当该异常发生,希望程序停止,因为在运行时出现了无法继续运算的情况,希望停止程序后对代码进行修正。

注意:自定义异常时,如果该异常可以处理,处理完后程序可以继续运行,那么就让该异常继承Exception;如果该异常的发生无法再继续进行运算,程序无法运行,就让该自定义异常继承RuntimeException

例:

class FuShuException extends RuntimeException
{
FuShuException(String msg)
{
super(msg);//在自定义异常类的构造函数内将异常信息传递给父类
}
}

总结:对于异常分两种

编译时被检测的异常
编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

throw语句单独存在时下面的语句访问不到,因为函数会结束(return语句也如此)

finally关键字

finally代码块定义一定执行的代码,通常用于关闭资源,比如数据库连接。

有些问题需要内部处理,之后告诉对方(分层思想),例:

class NoException extends Exception//自定义异常类
{
NoException(String msg)
{
super(msg);
}
}

public void method() throws NoException
{
try
{
连接数据库;
数据操作;
}
catch(SQLException e)
{
会对数据库进行异常处理;
throw new NoException();
}
finally
{
关闭数据库;
}
}

处理语句其他格式

第一个格式

try
{
}
catch()
{
}

第二个格式

try
{
}
catch()
{
}
finally
{
}

第三个格式

try
{
}
finally
{
}
注意:catch是用于处理异常的,如果没有catch就代表异常没有被处理过,此时如果该异常是检测型异常,该异常必须在函数上声明出去。

异常在子父类覆盖中的体现:

子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法只能抛出父类的异常或者该异常的子类,或者不抛异常。如果子类发生其他异常,只能内部处理,不能抛。
如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类方法的子集。
如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须进行try处理,绝对不能抛。

异常使得正常流程代码和问题发生的代码相分离,无需使用if语句判断,阅读性强
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: