目录
异常:代表程序出现的问题
运行时异常和编译时异常的区别?
异常的作用:
异常的处理方式:
异常中常见的方法:
抛出异常:
自定义异常:
异常:代表程序出现的问题
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 zeroat 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: 6at 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-10at ExceptionDemo.GirlFriend.setName(GirlFriend.java:30)at ExceptionDemo.demo3.main(demo3.java:13)Process finished with exit code 1
可以看到,输出异常的时候会打印自定义的信息:长度应该是3-10