异常:在运行时发生的不正常情况
public class ExceptionDemo{
public static void main(String[]args){
int []arr = new int[3];
System.out.println(arr[3]);
}
}
异常处理办法:
早期时:以前正常流程代码和问题处理代码相结合, 劣势:问题处理代码和正常流程代码结合一起,阅读性差
现在将正常流程代码和问题处理代码分离。
if(time<0){
new FuTime();//代表着时间为负的情况,这个对象中会包含着问题的名称,信息,位置等信息。
}
java对异常的处理方法。
在java中用类的形式,对不正常情况进行了描述和封装对象。
1.其实异常就是java通过面向对象 的思想将问题封装成了对象。用异常类进行描述。
2.不同的问题用不同的类进行具体的描述,例:数组角标越界,角标为空。所以问题有多少,异常类有多少,将其共性向上抽取,形成了异常体系。
3.异常体系
该体系特点:子类的后缀名都是用其父类名作为后缀,可读性高
最终错误分为了两大类:
Throwable:异常类的共同父类,具有可抛性,无论是error还是异常,都是问题,
问题发生就应该可以跑出,让调用者知道并处理,该体系的特点就在于Throwable 及其所有的子类都具有可抛性
1.一般不可处理的(用error类来表示) 特点:是由jvm抛出的严重性的问题,这种问题发生一般不针对性处理,直接修改程序。
2.可以处理的(用exception类来表示)
可抛性:
能够被throw,throws这两个关键字所操作的类和对象都具备可抛性。
虚拟机在发生异常的位置新建对象,记录发生错误的位置,错误类型,名称。然后将该对象封装后抛出,给调用者(最终抛给虚拟机)。
当代码执行到发生异常的位置时,会终端代码的执行,抛出异常,异常代码后的代码不执行。
抛出异常时的提醒信息可以自定义:
//可以自行更改条件尝试不同输出
class Demo{
public int method(int[]arr,int index){
if(arr==null){
throw new NullPointerException("数组的引用不能为空");
}
if(index>=arr.length){
throw new ArrayIndexOutOfBoundsException("数组的角标越界了,你是不是疯了,哥们儿:"+index);
}
if(index<0){
throw new ArrayIndexOutOfBoundsException("数组的角标为负整数了,哥们,你是真疯了:"+index);
}
return arr[index];
}
}
class ExceptionDemo2{
public static void main(String[]args){
int []arr = new int [3];
Demo d = new Demo();
int num = d.method(arr,-30);
System.out.println("num="+num);
System.out.println("over");
}
}
自定义异常:
对于角标是整数不存在,可以用角标越界来表示。 对于负数为角标的情况,准备用负数角标异常来表示。
负数角标异常这种异常在java中并没有定义过。 那就按照java异常的创建思想,面向对象,将负数角标进行自定义描述,并将其封装成对象。
这种自定义的问题描述,称为自定义异常。
//如果让一个类成为异常类,必须要继承异常体系,因为只有成为异常体系的子类才具有可抛性,才能被throw,throws所操作。
//如果一个方法内部可能出现异常,要在方法上先进行异常声明,不然会出现未报告的异常错误。
//主类
class ExceptionDemo3{
public static void main(String[]args) throws FuShuIndexException{
int []arr = new int [3];
Demo d = new Demo();
int num = d.method(arr,-30);
System.out.println("num="+num);
System.out.println("over");
}
}
//自定义异常类
class FuShuIndexException extends Exception{
void FuShuIndexException(){
}
FuShuIndexException(String msg){
super(msg);//调用父类方法
}
}
//Demo类
class Demo{
public int method(int[]arr,int index) throws FuShuIndexException{
if(index<0){
throw new FuShuIndexException("角标变成负数了");
}
return arr[index];
}
}
throw与throws的区别:
throw 修饰对象
throws修饰类
异常的分类:
1.编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系和其子类。 这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。 这样的问题都可以针对性处理。
2.编译时不检测异常(运行时异常):就是Exception中的Runtime体系和其子类 这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者原因导致的,或者引发了内部状态的改变导致的。
那么这种问题一般不处理,直接编译通过,在运行时让调用时的程序强制停止,让调用者对代码进行更正
对异常的处理方法:
当知道调用的方法可能会有的异常能处理的时候,就捕获(try ,catch) 如果对此异常处理不了,就直接抛出
使用try,catch捕获异常,问题解决后会继续运行下面的代码。
class ExceptionDemo3{
public static void main(String[]args){
int []arr = new int [3];
Demo d = new Demo();
try{
int num = d.method(arr,-30);
System.out.println("num="+num);
}catch(FuShuIndexException e){
System.out.println("message:"+e.getMessage());
System.out.println(e);//输出语句中,会自动调用对象的toString方法,而且任何类都有toString方法。
e.printStackTrace();//jvm默认的异常处理机制
System.out.println("负数角标异常");
}
System.out.println("over");
}
}
class FuShuIndexException extends Exception{
void FuShuIndexException(){
}
FuShuIndexException(String msg){
super(msg);
}
}
class Demo{
public int method(int[]arr,int index) throws FuShuIndexException{
if(index<0){
throw new FuShuIndexException("角标变成负数了");
}
return arr[index];
}
}
当一个try会出现多个异常的时候,写多个catch即可
如果在多个catch中存在Exception类时,这个catch要写在最后一个,否则编译失败。
class ExceptionDemo3{
public static void main(String[]args){
int []arr = new int [3];
Demo d = new Demo();
try{
int num = d.method(null,30);
System.out.println("num="+num);
}catch(FuShuIndexException e){
e.printStackTrace();//jvm默认的异常处理机制
}catch(NullPointerException e){
e.printStackTrace();
}
System.out.println("over");
}
}
class FuShuIndexException extends Exception{
void 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];
}
}
异常的处理原则:
1。方法内部如果抛出需要检测的异常,那么方法上必须要声明。或者在方法内用try,catch捕捉,否则编译失败。
2。如果调用到了声明异常的方法,要么try,要么throws,否则编译失败。
3。见到异常就要做处理,能够处理的进行try,不能处理的直接抛出。
4。一个功能如果抛出了多个异常,那么调用时,必须有多个对应的catch进行针对性处理。内部几个异常,就需要几个catch
finally:其中的代码一应会执行,除非是虚拟机结束了(System.exit(0))
通常用于释放资源。
try catch finally组合特点:
1.try catch finally
2.try catch(多个) 没有必要资源需要释放时,可以不用定义finally.
3.try finally ,异常可以抛出,但是自己打开的资源必须关掉,否则会浪费资源 void show() throws Exception{ try{
//开启资源
throw new Exception; } finally{
//关闭资源 } }
异常的注意事项:
1.子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类
2.如果父类抛出多个异常,那么子类只能抛出父类异常的子集。
3.如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛出异常。