Java常见异常处理
Exception类:
在java中用类的形式对不正常情况进行了描述和封装对象,异常就是java通过面向对象的思想将问题封装成了对象。
异常发生的原因有很多,通常包含以下几大类:
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信时连接中断
- JVM内存溢出
Throwable:
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
//该体系的特点就在于Throwable及其所有的子类都具有可抛性。
可抛性到底指的是什么呢?怎么体现可抛性呢?
是通过两个关键字来体现的。
throws和throw ,凡是可以被这两个关键字所操作的类和对象都具备可抛性。
|--1,一般不可处理的:Error
特点:是由jvm抛出的严重性的问题。这种问题发生一般不针对性处理,直接修改程序。
|--2,可以处理的:Exception
异常的分类:
1,编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。这样的问题都可以针对性的处理。
2,编译时不检测异常(运行时异常,比较多见):就是Exception中的RuntimeException和其子类。
这种问题的发生无法让功能继续,运算无法进行,更多是因为调用者的原因导致的或者引发了内部状态的改变导致的。
那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停止,让调用者对代码进行修正。
自定义异常:
有的异常在Java中并没有定义过,可以按照java异常的创建思想,面向对象,将异常进行自定义描述。并封装成对象。声明异常的目的是让调用者来处理这些问题。
自定义异常时,要么继承Exception。要么继承RuntimeException。
*继承Exception需要throws来声明,继承RuntimeException不需要。*
throws 和throw的区别:
1,throws使用在函数上,throw使用在函数内。
2,throws抛出的是异常类,可以抛出多个,用逗号隔开。throw抛出的是异常对象。
异常处理的捕捉形式:(常用)
这是可以对异常进行针对性处理的方式。
具体格式是:
try { //需要被检测异常的代码。 } catch(异常类 变量)//该变量用于接收发生的异常对象 { //处理异常的代码。 } finally { //一定会被执行的代码。 }
异常处理的原则:
1,函数内容如果抛出需要检测的异常,那么函数上必须要声明。
否则必须在函数内用trycatch捕捉,否则编译失败。
2,如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。
3,什么时候catch,什么时候throws?
功能内容可以解决,用catch。
解决不了,用throws告诉调用者,由调用者解决 。
4,一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。
内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
例:
class FuShuIndexException extends Exception//*自定义异常*:输入的数组角标为负* { FuShuIndexException() {}
FuShuIndexException(String msg) { super(msg); } } class Demo { public int method(int[] arr,int index)throws NullPointerException,FuShuIndexException { if(arr==null) throw new NullPointerException("没有任何数组实体"); if(index<0) throw new FuShuIndexException("数组角标不能为负"); return arr[index]; } } class ExceptionDemo4 { public static void main(String[] args) { int[] arr = new int[3]; Demo d = new Demo(); try { int num = d.method(arr,-1); System.out.println("num="+num); } catch(NullPointerException e) { System.out.println(e.toString()); } catch (FuShuIndexException e) { System.out.println("message:"+e.getMessage()+"\n"); System.out.println("string:"+e.toString()+"\n");//对象变成字符串打印(一般是哈希值) e.printStackTrace();//jvm默认的异常处理机制就是调用异常对象的这个方法。 } /* catch(Exception e)//多catch,父类的catch放在最下面。(面试) { } */ System.out.println("over"); } }
运行结果:
message:数组角标不能为负 string:FuShuIndexException: 数组角标不能为负 FuShuIndexException: 数组角标不能为负 over at Demo.method(TestException.java:22) at ExceptionDemo4.main(TestException.java:35)
Finally代码块:
在异常出现后仍会运行的代码块,通常用于用于关闭(释放)资源。
几种代码组合形式:
1,
try catch finally
***例:*** 异常转换(封装)
void addData(Data d)throws NoAddException
{
连接数据库
try
{
添加数据。出现异常 SQLException();
}
catch(SQLException e)
{
//处理代码。
throw new NoAddException();//***处理不了的问题要继续抛出***,告诉调用者添加数据没有成功。
}
fianlly
{
//关闭数据库。
}
}
2,
try catch(多个)当没有必要资源需要释放时,可以不用定义finally。
3,
try finally 异常无法直接catch处理,但是资源需要关闭。
例:
void show()throws Exception { try { //开启资源。 throw new Exception(); } finally { //关闭资源。 } }
子父类异常的注意事项:
1,子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。
2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集。
简单说:子类覆盖父类只能抛出父类的异常or子类or子集。
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try .