一、异常的概念及分类
Exception:异常,代表程序可能出现的问题
Exception分为两类:
1、运行时异常:RuntimeException以及其子类,编译阶段不会出现异常提醒,在运行阶段会出现异常提醒
2、编译时异常:编译阶段出现异常提醒
二、异常处理的方式
1、JVM默认的处理方式
把异常的原因、异常的名称、异常出现的位置以红色字体打印在控制台
程序停止执行,异常后面的代码不会再执行
public class test1 {public static void main(String[] args) {/*1、JVM默认的处理方式把异常的原因、异常的名称、异常出现的位置以红色字体打印在控制台程序停止执行,异常后面的代码不会再执行*/System.out.println("你好");System.out.println(1/0);System.out.println("我的世界");System.out.println("java");// 你好// ArithmeticException// 只会输出你好和异常信息 出现异常后面的代码不会再执行}
}
2、自己处理捕获异常
如果自己不捕获并处理异常 系统就会处理异常 那么就在控制台输出错误信息 并终止程序 如果我们不想要终止程序就必须自己捕获并处理异常 这就是自己捕获并处理异常的好处
(1)语法
try{
可能出现异常的代码;
} catch(异常类名 变量名){
异常的处理代码;
}
快捷键:
选中可能出现异常的代码 ctrl+alt+t
目的:
当代码出现异常时,可以让程序继续往下执行
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/System.out.println("我的世界");/*此处出现算术异常,程序会创建一个码ArithmeticException类的对象 new ArithmeticException()然后拿着这个对象与catch的小括号中的对象进行对比 看是否匹配如果能接收 那么异常就会捕获 就会执行catch里面的代码当执行完try...catch后 程序会继续往下执行 输出java*/try {// 可能出现异常的代码System.out.println(1/0);}catch (ArithmeticException e){// 出现异常代码后执行的操作System.out.println("算术异常 被除数不能是0");}// 执行完try...catch后 程序会继续往下执行System.out.println("java");// 输出:// 我的世界// 算术异常 被除数不能是0// java}
}
(2)注意
1、如果try中代码没有出现异常,那么系统会执行完try中所有的代码,不会执行catch语句体(只有try语句体出现异常才会执行catch语句体)
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/try {// 可能出现异常的代码// 当没有出现异常时 会执行完所有的代码System.out.println("你好");System.out.println("java");}catch (ArithmeticException e){// 出现异常代码后执行的操作// 当没有出现异常时 不会执行代码System.out.println("算术异常 被除数不能是0");}// 执行完try...catch后 程序会继续往下执行System.out.println("我的世界");// 输出:// 你好// java// 我的世界}
}
2、如果try中代码有多个异常,但是catch中罗列的异常情况没有包括try中的所有异常,程序可能终止,可能不终止
如果程序没有捕获到异常就会终止程序(相当于try...catch白写了 最终还是交给虚拟机进行处理) 如果捕获到了就不会终止程序
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/int [] arr=new int[] {1,2,3,4,5};try {// 可能出现异常的代码System.out.println(arr[10]);System.out.println(1/0);}catch (ArithmeticException e){// 出现异常代码后执行的操作System.out.println("算术异常 被除数不能是0");}System.out.println("我的世界"); // 因此不会输出我的世界/*分析:System.out.println(arr[10]);出现了索引异常 就会与catch括号中的异常进行匹配现在 ArithmeticException e 与 new ArrayIndexOutOfBoundsException()无法匹配错误捕获不到由于 ArrayIndexOutOfBoundsException 异常没有在 catch 块中被捕获处理,程序会在此处中断,不会继续执行后面的代码*/// 输出:// ArrayIndexOutOfBoundsException}
}
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/int [] arr=new int[] {1,2,3,4,5};try {// 可能出现异常的代码System.out.println(1/0);System.out.println(arr[10]);}catch (ArithmeticException e){// 出现异常代码后执行的操作System.out.println("算术异常 被除数不能是0");}System.out.println("我的世界"); /*分析:System.out.println(1/0);出现了算术异常 就会与catch括号中的异常进行匹配因此trySystem.out.println(arr[10]);就不会执行(即使有错误也执行不到)现在 ArithmeticException e 与 new ArithmeticException()匹配错误捕获到 由于捕获到错误就会执行catch的语句体执行完try...catch之后 程序继续往下执行 输出我的世界*/// 输出:// 算术异常 被除数不能是0// 我的世界}
}
解决方法:写多个catch语句罗列所有的异常情况,如果这些异常存在父子关系,那么父类一定要写在最下面
根据多态的概念 父类可以接收子类的对象 如果将父类异常放在上面 那么try语句体出现的异常都会被父类异常接收 那么父类异常下面的异常永远执行不到
在JDK7以后 如果多个catch的语句体执行的操作是一样的 那么异常可以写在一个catch语句体中
注意:写在同一个catch括号中的异常不能存在父子关系 各个异常之间用|隔开 不能用||隔开
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/int [] arr=new int[] {1,2,3,4,5};try {// 可能出现异常的代码// 每次只捕获一个错误 捕获到了就执行catch语句体System.out.println(1/0);System.out.println(arr[10]);}catch (ArrayIndexOutOfBoundsException |ArithmeticException e){// 不能写成ArrayIndexOutOfBoundsException ||ArithmeticException e// 或者ArrayIndexOutOfBoundsException e|ArithmeticException e// 出现异常代码后执行的操作System.out.println("异常");}System.out.println("我的世界"); // 为什么不能输出}
}
(3)问题总结
(4)对异常常见的处理方法
1、异常对象名称.getMessage();
该方法返回有关异常的简短描述
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/int [] arr=new int[] {1,2,3,4,5};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {// e.getMessage() 返回值是有关异常的简短描述String str= e.getMessage();System.out.println(str);}System.out.println("我的世界");// Index 10 out of bounds for length 5// 我的世界}
}
2、异常对象名称.toString();
该方法返回有关异常的简短描述
public class test1 {public static void main(String[] args) {/*2、自己处理语法:try{可能出现异常的代码;} catch(异常类名 变量名){异常的处理代码;}*/int [] arr=new int[] {1,2,3,4,5};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {// e.getMessage() 返回值是有关异常的简短描述String str= e.toString();System.out.println(str);}System.out.println("我的世界");// java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5// 我的世界}
}
3、异常对象名称.printStackTrace();
无返回值 直接在控制台以红色字体打印异常信息 不会终止程序
3、抛出异常
用于方法中可能出现的异常
(1)throws
写在方法的定义处,表示声明一个异常,告诉调用者使用本方法可能会有哪些异常,如果是运行时异常,那么throws在方法定义处抛出的异常可以不写,但如果是编译时异常,那么throws在方法定义处抛出的异常必须要写
语法:
public void 方法() throws 异常类名1,异常类名2...{
....
}
(2)throw
写在方法内,结束方法,手动抛出异常对象,交给调用者,方法中异常下面的代码就不再执行力
语法:
public void 方法() {
throws 异常类名1,异常类名2...
}
public class test1 {public static void main(String[] args) {// 对抛出的异常 我们需要进行处理 可以采取自己捕获错误的方式 try...catchint [] arr=new int[0];try {System.out.println(getMax(arr));} catch (NullPointerException e) {System.out.println("空指针异常");}catch (ArrayIndexOutOfBoundsException e) {System.out.println("数组越界访问异常");}}// throws NullPointerException,ArrayIndexOutOfBoundsException// 这段代码告诉调用者 调用getMax方法可能会出现NullPointerException,ArrayIndexOutOfBoundsException的错误// 因为NullPointerException,ArrayIndexOutOfBoundsException都属于运行时异常RuntimeException// 因此在方法头定义处可以不写throws NullPointerException,ArrayIndexOutOfBoundsExceptionpublic static int getMax (int [] arr)throws NullPointerException,ArrayIndexOutOfBoundsException{// 当数组为null意味着该数组变量不指向任何数组的内存地址if(arr==null){// 抛出空指针异常给调用者throw new NullPointerException();}// 当没有数组元素时 抛出索引越界异常if(arr.length==0){// 抛出索引越界异常给调用者throw new ArrayIndexOutOfBoundsException();}int max=arr[0];for (int i = 1; i < arr.length; i++) {if(arr[i]>max){max=arr[i];}}return max;}
}
抛出异常通常和捕获异常相结合
三、自定义异常
创建步骤:
1、定义异常类
类名见名知意
2、写继承关系
如果是编译时异常就继承Exception
如果是运行时异常就继承RuntimeException
3、定义空参构造
4、定义带参构造