异常
1、异常的概念
2、异常体系图★
3、常见的异常
4、异常处理的概念
5、异常处理的分类 ★
6、自定义异常【了解】
7、throw和throws的对比【面试题】
异常的概念
异常的体系图
常见的运行异常介绍
NullPointerException 空指针异常
当试图使用null对象的属性或方法时
ArrayIndexOutOfBoundsException 数组下标越界异常
当试图使用数组的索引超过范围:0——length-1
ClassCastException 类型转换异常
当试图将不是该类型的实例强转成该类型
ArithmeticException 数学运算异常
除数为0时
NumberFormatException 数字格式不正确
当试图将字符串转换成数值时,如果该字符串不是有效的数值格式
异常处理的概念
处理程序中发生的不正常现象,称为异常处理
异常处理好处
a、提高用户的体验性(可打印友好提示)
b、让正常的代码和容易出错的代码进行了分离,提高代码的语义性和维护性
c、让try catch块后面的语句继续执行
异常处理的分类 ★
方式一:自己处理
语法
try{
①
//容易出现异常的代码②
③
}catch(异常类型A e){
//处理语句1 ④
}catch(异常类型B e){
//处理语句1 ⑤
}catch(异常类型C e){
//处理语句1 ⑥
}
finally{
//最后一定执行的语句 ⑦
}
执行顺序
如果 try 出现了异常,则 try 块中下面的语句将不再执行,而是执行 catch 块的语句,最后执行 finally 块的语句
如果 try 未出现异常,则 try 块中下面的语句需要执行,catch块的语句不再执行,最后执行 finally 块的语句
注意事项
- catch块可以省略
- 也可以多个,但如果catch块中有父类异常类型,必须放在最后!
- finally块可以省略
例1
import java.util.Scanner;
public class TestException4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// try部分运行到错误处,将不会再往下执行
try{
// 其中有可能有多种错误,则后面可放多个 catch 块
System.out.println("请输入a:");
String a = input.next();
System.out.println("请输入b:");
String b= input.next();
//判断两个字符串是否相等
// a=null;// 若将a赋成null,则不管是什么错误,下面只会报空指针错误,因为try下面部分都不会再执行
if(a.equals(b)){
System.out.println("相等");
}
//将字符串转换成int类型
int num1 = Integer.parseInt(a);
int num2 = Integer.parseInt(b);
//数学运算
System.out.println("div="+num1/num2);//容易出现异常
System.out.println("哈哈");
// 若某种错误忘记是哪一种,则直接用 Exception 父类,但这个catch块要放到最后
System.out.println(args[0]);
}catch(NumberFormatException e){
System.out.println("数字格式不正确吧");
}catch(ArithmeticException e){
System.out.println("除数为0了吧!");
}catch(NullPointerException e){
System.out.println("空指针了吧");
}catch(Exception e){
// catch块中有父类异常类型,必须放在最后
System.out.println("下标越界吧");
}finally{
// 最后一定要执行的语句
System.out.println("try catch块后面的语句");
}
}
}
例2
public class TestException1 {
static int method(){
try {
String[] names = new String[3];
if(names[1].equals("john")){
System.out.println(names[1]);
}
else{
names[3] = "lucy";
}
return 1;
} catch (ArrayIndexOutOfBoundsException e) {
// TODO Auto-generated catch block
return 2;
} catch (NullPointerException e) {
// TODO Auto-generated catch block
return 3;
} finally{
// 若此句不注释,则无论怎么执行都是只返回4,因为try catch无论怎样,最后总是执行finally块中的
// return 4;
//此时返回3并且输出222222
System.out.println("222222");
}
//此句不会再执行
System.out.println("333333");
}
public static void main(String[] args){
// Scanner input = new Scanner(System.in);
// int i=input.nextInt();
// System.out.println(i);
System.out.println(method());
}
}
总结
并不是try块中的语句越多越好,因为会影响效率(try要检测错误类型,所以会影响效率)
尽量使用多个catch代替多个try catch(将出错部分都放入try中,然后多个catch处理)
方式二:抛给他人处理
语法
修饰符 返回类型 方法名(参数列表) throws 异常类型A{
//容易出现异常的代码
}
异常类型A为 方法中出现的异常类型或其父类类型
执行机制
将异常抛给调用方,调用方可以继续处理,如果继续往上抛,可以一直抛到jvm,jvm则最后处理方式:打印错误堆栈日志!
如果对异常不进行任何处理,则默认采取的方式为抛出的方式
子类方法抛出的异常要么相同,要么为其子类类型
例1
public class TestException5 {
public static void main(String[] args ) throws Exception {
method1();
}
private static void method1() throws Exception {
method2();
}
private static void method2() throws Exception {
method3();
}
private static void method3() throws Exception {
method4();
}
private static void method4() throws Exception{
int[] arr = {1,2,3};
System.out.println(arr[3]);//下标越界异常
}
}
例2
class Son extends Father{
@Override
public void method() throws NullPointerException {
super.method();
}
}
class Father{
public void method() throws RuntimeException{
}
}
生成异常对象
- 系统自动生成,只能针对系统定义好的异常类型
- 手动抛出,可以针对系统定义好的异常类型或自定义的异常类型
throw new 异常类型();
例
public class TestException7 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("年龄:");
int age = input.nextInt();
if(age>120 || age<0){
//生成一个异常对象
// AgeIllegalException ae = new AgeIllegalException("年龄不合法!");
// throw ae;
// throw new AgeIllegalException("年龄不合法!"); //与上面两句效果相同
try {
//下面两句效果一样,因此自定义异常可有可无
throw new RuntimeException("年龄不合法!");
// throw new AgeIllegalException("年龄不合法!");
} catch (Exception e) {
// e.printStackTrace();
System.out.println("出错了,信息:"+e.getMessage());
}
}
System.out.println("年龄是:"+age);
}
}
class AgeIllegalException extends RuntimeException{
private static final long serialVersionUID = 1L;
public AgeIllegalException(String msg){
super(msg);
}
public AgeIllegalException(){
}
}
面试
- 生成异常方式和区别
- throw 和 throws对比
意思 | 后面跟的东西 | 放的位置 | |
---|---|---|---|
throw | 手动生成异常 | 异常对象 | 方法体中,一般搭配if使用 |
throws | 异常生成的另一种方式 | 异常类型 | 方法声明处 |