异常处理
1.异常处理概述
1.1使用返回值状态标示异常
在java之前,异常通常采用返回值的方式来标示程序出现的异常状况,但有几点不好之处。
1.一个API可以返回任意的返回值,返回值本身并不代表异常状况和异常的具体情况,需用用户自己判断并解释返回值的意义。
2.其次,并没有一种机制保证异常状况一定得到处理。
1.2异常处理机制
当程序发生异常时,程序从程序代码处跳出,java虚拟机会自动找到与该异常有关的catch块,如果找到,将控制权交到catch块中,然后执行catch块中的程序,然后继续往下执行,try块中异常不会重复执行。如果没有找到处理该异常的catch块,将代码交到finally块中。
2.异常的捕获和处理
2.1 Throwable、EXception、Error
java异常结构中定义有Throwable类,Exception和Error是其派生子类。
Exception代表网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常
Error:表示java运行时环境出现的错误。如:JVM内存资源耗尽
2.2 try-catch
若try中抛出一种或几种异常,后面的catch分别对这些异常做出相应的处理.
若没有异常产生所有的catch块都被略过,catch块中是对异常进行处理的代码。
2.3多个catch
每个try语句块可以伴随一个或多个catch语句块,用于处理可能产生不同类型的异常,
catch异常类型从上到下顺序应为从子类到父类。
2.finally的作用
finally为所有异常处理提供了一个统一的出口。使得控制流程转到其他部分之前,能对程序统一管理
无论try块中是否抛出异常,finally指定的代码都应被执行。
通常finally语句用于进行资源释放的工作,如:关闭文件,删除临时文件。
2.5 throw关键字
当程序发生异常时,会抛出对应的异常,若有时想要自行抛出异常可以使用“throw”关键字,并生成指定异常对象后抛出。
2.6 throws关键字
在方法中可能发生很多异常,当不想再方法中处理这种无异常,可以再方法中通过声明“throws ”关键字来将方法中异常抛出。
2.7重写方法时的throws
如果使用继承时,在父类某个方法声明了throws,在子类重写时,抛出的异常要小于等于该异常,不能有额外异常。
3.Java异常API
3.1 RuntimeException
异常可以分为可检测异常和非检测异常
可检测异常是指通过编译器验证对于抛出的异常,编译器会强制执行处理或声明规则,不捕捉异常,编译器就通不过,不允许编译
非检测异常,不遵循处理或者声明原则,在产生此类异常时,编译器不会检查是否解决了这样一个异常。
RuntimeException是非检测异常
3.2常见RuntimeException异常
代码如下:
/**
* 测试空指针异常
*/
public void testNullPointerException(){
String str=null;
//会引发空指针异常
System.out.println(str.length());
}
/**
* 测试数组下标越界异常
*/
public void testArrayIndexOfBoundsException(){
byte[] bytes="hello".getBytes();
//会引发数组小标越界异常
System.out.println(bytes[bytes.length]);
}
/**
* 测试数学异常
*/
public void testArithmeticException(){
//引发数学异常
System.out.println(5/0);
}
/**
* 测试强制类型转换异常
*/
public void testClassCastException(){
Object obj="hello";
//会引发强制类型转换异常
Integer i=(Integer)obj;
}
/**
* 测试NumberFormat异常
*/
@Test
public void testNumberFormatException(){
//会引发NumberFormat异常
int num=Integer.parseInt("a");
}
4.Exception常用API
4.1 printStackTrace
printStackTrace用来表示可以输出错误信息,用来跟踪异常事件发生时执行的堆栈内容
4.2getMessage
声明可以得到有关异常事件的信息
4.3 getCause
很多时候,一个异常是由另一个异常导致的异常而被抛出的时候,java库和开放源代码包装成另一种异常.
getCause是获取异常出现的原因(根异常)
5. 自定义Exception
5.1自定义异常的意义
有时候为了更好的处理和捕获来呈现更好的用户体验,需要开发者自定义异常
5.2继承Exception自定义异常
代码如下:
public class CopyException extends Exception {
public CopyException(){
super();
}
public CopyException(String message,Throwable cause){
super(message,cause);
}
public CopyException(String message){
super(message);
}
public CopyException(Throwable cause){
super(cause);
}
}
@Test
public void testCopy1() throws CopyException{
FileInputStream fis=null;
FileOutputStream fos=null;
try{
fis=new FileInputStream("fos.dat");
fos=new FileOutputStream("fos_copy4.dat");
int d=-1;
while((d=fis.read())!=-1){
fos.write(d);
}
System.out.println("复制完毕");
}catch(FileNotFoundException e){
//抛出自定义异常
throw new CopyException("文件没有找到",e);
}catch(IOException e){
throw new CopyException("读写异常",e);
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}