Java-异常处理
一、异常概念
异常概念:程序执行时出现的问题,会导致JVM的非正常停止
注意:
1.异常本身是一个类,产生异常就是创建并抛出了一个异常类的对象,Java处理异常的方式是中断处理 。
2.异常不是语法错误,语法错误,编译时会报错,不会产生字节码文件。
异常的根类java.lang.Throwable,有两个子类,java.lang.Error和java.lang.Exception,平常所言异常为java.lang.Exception。
二、throw关键字
throw关键字:用来在指定方法中抛出一个指定的对象。
使用步骤:
1.创建一个异常对象,封装一些异常提示信息,信息可以根据需要编写。
2.通过throw关键字把异常信息返回给调用者,并结束当前方法的执行。
使用格式:
throw new xxxException(“异常产生的原因”)
注意事项:
1.throw关键字必须写在方法内部。
2.throw关键字new的对象必须是Exception或Exception的子类对象。
3.throw关键字抛出了指定异常对象,如果是RuntimeException或RuntimeException的子类对象,可以不处理,默认交给JVM处理,即打印异常信息,中断程序,如果是编译期异常,我们就必须进行处理,使用throws或者try-catch。
public class ExceptionDemo03 {
public static void main(String[] args) {
int[] array=null;
int a=getNum(array,1);
System.out.println(a);//抛出异常java.lang.RuntimeException: 数组为空
}
public static int getNum(int[] array,int index){
//如果数组为空,我们可以创建一个空指针异常,告知调用者
if(array==null){
throw new RuntimeException("数组为空");//RuntimeException可以交给JVM处理
}
return array[index];
}
}
三、Objects中静态方法requireNonNull()
Objects中静态方法:
public static T requireNonNull(T obj):查看指定对象是否为null。
public class ExceptionDemo04 {
public static void main(String[] args) {
int[] array=null;
method(array);//NullPointerException: 数组为空
}
public static void method(Object o){
// //对参数进行判断
// if(o==null){
// throw new NullPointerException("数组为空");
// }
//对传递的参数进行判断,可以简化书写
//Objects.requireNonNull(o);
//可以进行对上面方法进行重写,进行异常信息的编写
Objects.requireNonNull(o,"数组为空");
}
}
四、异常处理方式
1.throws(异常处理第一种方式)
throws关键字(声明异常):
用在方法声明之上,用于表示当前方法不处理异常,而是提醒方法的调用者来处理异常,也就是自己不处理交给别人处理。
使用格式:
修饰符 返回值类型 方法名(参数列表) throws XXXException,YYYException…{//可以抛出多个异常
throw new XXXException(“异常信息”);
throw new YYYException(“异常信息”);
}
注意事项:
1.throws关键字只能在方法声明处写。
2.throws关键字后声明的异常必须是Exception或者是Exception的子类。
3.throws可以抛出多个异常,方法内部有多个异常对象,throws关键字后也必须声明相应数目的异常,除非是多个异常。对象存在子父类关系,直接声明父类异常对象即可。
4.调用一个声明抛出的方法,就必须处理异常
public class ExceptionDemo05 {
public static void main(String[] args) throws Exception {
int[] array=null;
getNum(array,0);//继续抛出异常,最后交给JVM处理,即打印异常信息,中断程序
//java.lang.Exception: 数组为空
}
public static int getNum(int[] array,int num) throws Exception{
if(array==null){
throw new Exception("数组为空");//不是RuntimeException,必须手动处理,抛出异常,交给方法调用者处理
}
return array[num];
}
}
2.try-catch(异常处理第二种方式)
try-catch(捕获异常):
Java中对可能出现异常的语句进行捕获,可以对异常使用指定方式进行处理(不交给别人处理,自己进行处理)。
格式;
try{
可能产生异常的代码
}catch(定义一个用来接收try抛出的异常对象的变量 Exception e){
异常的处理逻辑,表示怎么处理对象,一般会把异常信息记录到一个日志中
}
注意:
1.try可能会抛出多个异常,那么可以使用多个catch来处理这些异常。
2.如果try中产生了异常,就会执行catch后的代码,然后继续向下执行try-catch后面的代码如果不产生异常,就不会执行try-catch语句。
public class ExceptionDemo06 {
public static void main(String[] args) {
int[] array=null;
try {
getNum(array,0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//使用try-catch,执行完后,程序继续向下执行
System.out.println("try-catch语句后的代码");//输出结果:try-catch语句后的代码
}
public static int getNum(int[] array,int num) throws Exception{
if(array==null){
throw new Exception("数组为空");//不是RuntimeException,必须手动处理,抛出异常,交给方法调用者处理
}
return array[num];
}
}
五、throwable类中异常处理方法
Throwable类中定义三个异常处理的方法:
String getMessage():返回throwable的简短信息。
String toString():返回throwable的详细信息。
void printStackTrace():JVM打印异常对象,默认方法,打印信息(位置,原因,内容)最全面。
public class ExceptionDemo07 {
public static void main(String[] args) {
int[] array=null;
try {
getNum(array,0);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());//输出结果:数组为空 简短信息
System.out.println(e.toString());//输出结果:java.lang.Exception: 数组为空 详细信息
//e.printStackTrace();//默认方法,以红色字体打印在控制台,异常产生的位置,原因,内容
}
}
public static int getNum(int[] array,int num) throws Exception{
if(array==null){
throw new Exception("数组为空");
}
return array[num];
}
}
六、finally关键字
finally:用于存放异常不管是否发生都需要执行的代码。
注意事项:
1.finally需要和try-catch一起使用,不能单独使用
2.finally一般用于资源释放,无论程序是否出现异常,都对资源进行释放
格式:
try{
可能产生异常的代码
}catch(定义一个用来接收try抛出的异常对象的变量 Exception e){
异常的处理逻辑,表示怎么处理对象,一般会把异常信息记录到一个日志中
}finally{
不管异常是否产生都会执行的代码
}
public class ExceptionDemo08 {
public static void main(String[] args) {
int[] array=null;
try {
//可能产生异常的代码
getNum(array,0);
} catch (Exception e) {
// TODO Auto-generated catch block
//异常的处理方法
e.printStackTrace();
}finally{
System.out.println("不管异常发生,代码都会执行");//输出结果:不管异常发生,代码都会执行
}
}
public static int getNum(int[] array,int num) throws Exception{
if(array==null){
throw new Exception("数组为空");
}
return array[num];
}
}
七、异常处理注意事项
1.多个异常处理方法
多个异常处理方法:
1.多次捕获,多次处理(多个try,多个catch)
2.一次捕获,多次处理(一个try,多个catch)
注意:catch里定义的异常变量,如果有子父类关系,那么子类异常变量必须写在上面,否则会出现多态现象,导致异常
3.一次捕获,一次处理(一个try,一个catch)
public class ExceptionDemo09 {
public static void main(String[] args) {
int[] array1={1,2,3};
ArrayList<Integer> list1=new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
System.out.println(array1[3]);//没有3索引 ArrayIndexOutOfBoundsException
System.out.println(list1.get(3));//没有3索引 IndexOutOfBoundsException
//多个异常处理方法:
//1.多次捕获,多次处理(多个try,多个catch)
try{
int[] array2={1,2,3};
System.out.println(array2[3]);
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
try{
ArrayList<Integer> list2=new ArrayList<>();
list2.add(1);
list2.add(2);
list2.add(3);
System.out.println(list2.get(3));
}catch(IndexOutOfBoundsException e){
e.printStackTrace();
}
//2.一次捕获,多次处理(一个try,多个catch)
// 注意:catch里定义的异常变量,如果有子父类关系,那么子类异常变量必须写在上面
try{
int[] array2={1,2,3};
System.out.println(array2[3]);
ArrayList<Integer> list2=new ArrayList<>();
list2.add(1);
list2.add(2);
list2.add(3);
System.out.println(list2.get(3));
// }catch(IndexOutOfBoundsException e){
// e.printStackTrace();
// }
// catch(ArrayIndexOutOfBoundsException e){ //错误写法,子类要写在上面,程序执行是从上往下匹配,如果子类写在下面,会出现多态
// e.printStackTrace();
// }
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
catch(IndexOutOfBoundsException e){
e.printStackTrace();
}
//3.一次捕获,一次处理(一个try,一个catch),一般直接使用Exception e 即可
try{
int[] array2={1,2,3};
System.out.println(array2[3]);
ArrayList<Integer> list2=new ArrayList<>();
list2.add(1);
list2.add(2);
list2.add(3);
System.out.println(list2.get(3));
}catch(Exception e){
e.printStackTrace();
}
}}
2.其它事项
异常注意事项:
1.运行时异常,可以不捕获也不声明抛出。
2.如果finally里有return语句,永远返回finally中的结果,会对结果造成影响。
3.如果父类抛出多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是它的子类或者不抛出异常。
4.父类方法没有抛出异常,子类覆盖父类该方法也不会抛出异常。此时子类产生的异常,只能捕获处理,不能声明抛出。
3.如果父类抛出多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是它的子类或者不抛出异常
4.父类方法没有抛出异常,子类覆盖父类该方法也不会抛出异常。此时子类产生的异常,只能捕获处理,不能声明抛出
注意:子类和父类保持一致即可
*/
public class ExceptionDemo10 {
public void method01() throws IndexOutOfBoundsException,NullPointerException{}
public void method02() throws IndexOutOfBoundsException,NullPointerException{}
public void method03() throws IndexOutOfBoundsException,NullPointerException{}
public void method04(){}
}
class ExceptionDemo10Son extends ExceptionDemo10{
//子类覆盖父类方法时,抛出相同的异常
@Override
public void method01() throws IndexOutOfBoundsException, NullPointerException {
// TODO Auto-generated method stub
}
//子类覆盖父类方法时,抛出父类异常的子类
@Override
public void method02() throws ArrayIndexOutOfBoundsException, NullPointerException {
// TODO Auto-generated method stub
}
//子类覆盖父类方法时,不抛出异常
@Override
public void method03() {
// TODO Auto-generated method stub
}
//父类方法没有抛出异常,子类覆盖父类该方法也不会抛出异常。此时子类产生的异常,只能捕获处理,不能声明抛出
// @Override
// public void method04() throws Exception{ //不能声明抛出
// // TODO Auto-generated method stub
// }
@Override
public void method04() {
// TODO Auto-generated method stub
try {
throw new Exception("异常信息");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
八、自定义异常类
自定义异常类:可以根据自身需求,自己定义一个异常类
格式:
修饰符 class XXXException extends Exception/RuntimeException{
空参数构造方法
带异常信息的构造方法
}
注意:
1.自定义异常类一般是Exception结尾,用于说明其身份。
2.自定义异常类,就必须继承 Exception/RuntimeException。
自定义异常处理办法:
继承 Exception:编译期异常,需要进行throws或者try-catch处理
继承RuntimeException:运行期异常,可以不用处理,交给JVM处理