目录
异常:代表程序出现的问题
运行时异常和编译时异常的区别?
异常的作用:
异常的处理方式:
异常中常见的方法:
抛出异常:
自定义异常:
异常:代表程序出现的问题
Exception:叫做异常,代表程序可能出现的问题。我们通常会用Exception以及他的子类来封装程序出现的问题。
运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。运行时出现的异常(如:数组索引越界异常)
编译时异常:编译阶段就会出现异常提醒的。(如:日期解析异常)
运行时异常和编译时异常的区别?
编译时异常,除了RuntimeException和他的子类,其他都是编译时异常。
编译阶段需要进行处理,作用在于提醒程序员。
运行时异常:
RuntimeException本身和所有子类,都是运行时异常
编译阶段不报错,是程序运行时出现的。
一般是由于参数传递错误带来的问题。
异常的作用:
作用一:异常是用来查询bug的关键参考信息
public class demo4 { public static void main(String[] args) { int []arr={1,2,3,4}; System.out.println(arr[5]); } }我们把这段代码在控制台进行运行,会发现控制台会报下面的错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at ExceptionDemo.demo4.main(demo4.java:6)会发现出现了数组越界异常,并且at是指出错代码的位置,所以异常第一个作用就是告诉你出现了bug,以及bug的信息是什么?
作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
想想你下你作为一个调用者,假如要给名字进行赋值,但是你不知道赋值规则是什么?其实编写者在写规则的时候给名字命名了规则,比如必须包含某种符号等,你进行了调用,但是并没有把赋值结果告诉你,只是在控制台进行了调用,你就会很懵逼。这就需要返回异常的信息。
异常的处理方式:
1.JVM默认的处理方式
.把异常的名称,异常原因以及异常出现的位置信息输出在控制台
.程序停止执行,异常下面的代码不会执行
public class demo5 { public static void main(String[] args) { System.out.println(2/0); System.out.println("代码执行了吗");//异常下面的代码并没有执行 }
下面试控制台运行结果
Exception in thread "main" java.lang.ArithmeticException: / by zero 异常名称
at ExceptionDemo.demo5.main(demo5.java:5) 异常位置Process finished with exit code 1
2.捕获异常
格式:
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码
}
目的:当代码出现异常时,可以让程序继续往下执行,不会停止虚拟机.
例子:
public class demo1 { public static void main(String[] args) { try { System.out.println(2/0);//此处出现了异常,程序就会在这里创建一个ArithmeticException对象->new ArithmeticException() //拿着这个对象到catch的小括号中进行对比,看该异常是否被捕获,然后执行catch对应的代码. }catch (ArrayIndexOutOfBoundsException e){ System.out.println(e); }catch (ArithmeticException e){ System.out.println(e); }catch (Exception e){ System.out.println(e); } System.out.println("看看我执行了吗");//catch里面的代码执行完毕,会执行try...catch体系下面的代码 } }
控制台结果:
try....catch四问?
1.如果try中没有问题,怎么执行?
public class demo1 { public static void main(String[] args) { int []arr={1,2,3,4,5}; try { System.out.println(arr[0]); }catch (ArrayIndexOutOfBoundsException e){ System.out.println(e); }catch (ArithmeticException e){ System.out.println(e); }catch (Exception e){ System.out.println(e); } System.out.println("看看我执行了吗"); } } 控制台输出: 1 看看我执行了吗
可以看到:try没有遇到问题,会把try里面所有代码执行完毕,不会执行catch里面的代码
2.如果try中可能会遇到多个问题,怎么执行?
public class demo1 { public static void main(String[] args) { int []arr={1,2,3,4,5}; try { System.out.println(arr[6]); System.out.println(2/0); }catch (ArrayIndexOutOfBoundsException e){ System.out.println("索引越界"); }catch (ArithmeticException e){ System.out.println("数学异常"); }catch (Exception e){ System.out.println(e); } System.out.println("看看我执行了吗"); } } 控制运行结果: 索引越界 看看我执行了吗
可以看到:
当我们执行System.out.println(arr[6]);这里出现数组越界异常,他会直接进行进行对应的catch捕获,然后执行对应的代码,再执行try..catch块下面的代码。其中有一个小注意点:
当我们要捕获的异常,存在父子关系的时候:要把父亲放在最下面,想一下,如果父亲在下面,不管什么异常都会被父亲所捕获,那么下面的异常永远无法被捕获到。
第三问:try中的问题没有被捕获会怎么样?
public class demo1 { public static void main(String[] args) { int []arr={1,2,3,4,5}; try { System.out.println(2/0); }catch (ArrayIndexOutOfBoundsException e){ System.out.println("索引越界"); }catch (NullPointerException e){ System.out.println("数学异常"); } System.out.println("看看我执行了吗"); } } 控制台输出: Exception in thread "main" java.lang.ArithmeticException: / by zero at ExceptionDemo.demo1.main(demo1.java:8) Process finished with exit code 1
可以看到,try中没有捕获到对应的异常,那么就会执行虚拟机默认的处理方式
第四问:try中遇到多个问题,下面的代码还会执行吗?
从上面代码可以看出,try中遇到问题,就不会往下执行,会直接执行catch捕获的代码。但是try...catch块下面的代码还会执行。
异常中常见的方法:
方法名称 | 说明 |
public String getMessag() | 返回此throwable的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
这里只演示比较常用的
public class demo1 { public static void main(String[] args) { int []arr={1,2,3,4,5}; try { System.out.println(arr[6]); }catch (ArrayIndexOutOfBoundsException e){ e.printStackTrace(); }catch (NullPointerException e){ System.out.println("数学异常"); } System.out.println("看看我执行了吗"); } } 控制台输出: 看看我执行了吗 java.lang.ArrayIndexOutOfBoundsException: 6 at ExceptionDemo.demo1.main(demo1.java:8)
可以看到这个e.printStackTrace();仅仅把错误的信息输出在控制台,不会停止程序运行
抛出异常:
throws
写在方法定义出,表示声明一个异常 告诉调用这,使用本方法可能会有哪些异常?
编译时异常:必须要写
运行时异常:可以不写
格式:public void 方法() throws 异常类名1...{
....
}
例子:
public class throwDemo1 { public static void main(String[] args) { int []arr={}; int max= 0; try { max = getMax(arr); //getMax抛出异常之后,调用者可以选择处理或者不处理,但是这样的话会导致下面代码不能执行,所以用try...catch的方法 } catch (Exception e) { e.printStackTrace(); } System.out.println(max); } public static int getMax(int []arr){ /*throws NullPointerException 运行时异常我们可以省略不写*/ if(arr==null){ //手动创建一个异常对象,并把这个异常交给方法的调用者处理 //此时方法会结束,下面的代码不会再执行了。 throw new NullPointerException(); } int max=arr[0]; for (int i = 0; i < arr.length; i++) { if(arr[i]>max){ max=arr[i]; } } return max; } }
throw
下在方法内,结束方法
手动抛出异常对象,交给调用者,方法中下面的代码不在执行
public void 方法(){
thorw new NullPointerException();
}
//
自定义异常:
目的:让控制台的错误更加的见名知意
public void setName(String name) { int len=name.length(); if(len<3||len>10){ throw new NameFormatException("长度应该是3-10");//这里时自定义抛出的异常,满足自定义的需求 } this.name = name; } //自定义的异常类 public class NameFormatException extends RuntimeException{ public NameFormatException() { } public NameFormatException(String message) { super(message); } }案例:
package ExceptionDemo; import java.util.Scanner; public class demo3 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); GirlFriend gf=new GirlFriend(); try { System.out.println("输入姓名"); String name=sc.nextLine(); gf.setName(name); System.out.println("输入年龄"); int age=sc.nextInt(); gf.setAge(age); } catch (NumberFormatException e) { e.printStackTrace(); }catch (AgeOutOfBoundsException e){ e.printStackTrace(); } System.out.println(gf); } } 控制台输出: 输入姓名 aa Exception in thread "main" ExceptionDemo.NameFormatException: 长度应该是3-10 at ExceptionDemo.GirlFriend.setName(GirlFriend.java:30) at ExceptionDemo.demo3.main(demo3.java:13) Process finished with exit code 1
可以看到,输出异常的时候会打印自定义的信息:长度应该是3-10