一、异常
异常就是代表程序出现了问题,像我们之前学数组的时候碰到的数组越界异常,以及空指针异常等等都属于开发中经常能碰到的异常。
我们学习异常不是为了在以后中避免异常,而是学习碰到了异常以后该如何的处理。
1.1、异常的分类
Java的类库从java.lang.Throwable
类开始,它定义了所有类型的错误和超类。Throwable
分为两个主要子类:Error
和Exception
。
Error
:代表的系统级别错误(属于严重问题)系统一旦出现问题,sun公司会把这些错误封装成Error对象
。Error是给sun公司自己用的,不是给我们程序员用的。因此我们开发人员不用管它。
Exception
:叫做异常,代表程序可能出现的问题,我们通常会用Exception
以及他的子类来封装程序出现的问题。
RuntimeException
:RuntimeException及其子类叫运行时异常
,编译阶段不会出现异常提醒,运行时出现的异常(如:数组索引越界异常)
Exception下其他异常
:编译阶段
就会出现异常提醒的。(如:日期解析异常)
1.2、编译时异常以及运行时异常
什么叫编译时异常?
我们直接看这段代码
在这段代码中我们看到了一个红色波浪线,有点基础的都知道,如果不解决这个红色波浪线我们编译
肯定是不通过的,现在我们看看它报了什么错。
看,未处理异常,这种异常就是编译时异常,在编译阶段必须手动的处理,否则就会一直报错。
那什么叫运行时异常呢?
这段代码中我们明确的知道数组是越界的,但是却不会给我报错,只有我们运行程序的时候才会报错。数组越界异常
我们总体看一下这两类异常
二、异常的作用
2.1、查看BUG的相关信息
我们来看下面这个代码:你觉得会报错吗?
会的,空指针异常,这里说arr.add("hello")
是空指针,这里我们就能知道了,List集合不能这么创建。
再来看看这个代码:
通过异常我们能知道,其发生了越界的异常,能给我关键的信息。
2.2、查看底层情况
异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况,有时候可以手动抛出异常来处理事件。
三、异常处理方案
3.1、虚拟机默认处理异常
把异常的名称
,异常原因
及异常出现
的位置等信息输出在了控制台,然后程序停止执行,下面的代码不会再执行了,来看下列代码:
public static void main(String[] args){
List<String> arr = new ArrayList<String>();
arr.add("hello");
System.out.println(arr.get(0));
System.out.println(arr.get(1));
System.out.println(arr.get(0));
}
其执行结果为:
可以看到程序未出错之前的代码正常运行了,出错之后的没有运行。
3.2、手动处理异常
一般我们使用try...catch...
来手动处理异常。他的作用是当try代码中出现了异常之后,不影响下面的代码运行。
我们再来看这段代码:
public static void main(String[] args){
List<String> arr = new ArrayList<String>();
arr.add("hello");
System.out.println(arr.get(0));
try {
System.out.println(arr.get(1));
}catch (IndexOutOfBoundsException e){
System.out.println("索引越界");
}
System.out.println(arr.get(0));
}
其输出为:
我们可以看到程序正常的往下面运行了,他的原理也很简单,如果try里面代码块报错了,会new一个报错类型的对象,然后去catch参数里面的异常去比较,如果能接收,就会执行catch里面的代码。
四、try…catch
4.1、如果try中没有遇到问题,怎么执行?
正常运行,不会运行catch里面的代码
4.2、如果try中可能会遇到多个问题,怎么执行?
有多少个异常类型就捕获多少个异常类型,但是正常运行时候第一个问题发生的时候就不回继续运行try里面的代码了。
如果我们要捕获多个异常,并且这些异常中如果存在父子关系的话,那么父类一定要写在下面。
public static void main(String[] args){
List<String> arr = new ArrayList<String>();
arr.add("hello");
List<String> arr1 = null;
try {
arr1.add("hello");
System.out.println(arr.get(1));
}catch (IndexOutOfBoundsException e){
System.out.println("索引越界");
}catch (NullPointerException n){
System.out.println("空指针异常");//空指针异常
}
System.out.println(arr.get(0));//hello
}
4.3、如果try中遇到的问题没有被捕获,怎么执行?
没有捕获的话就相当于白写try…catch了,还是会调用JVM的异常处理,直接停止代码。
public static void main(String[] args){
List<String> arr = new ArrayList<String>();
arr.add("hello");
List<String> arr1 = null;
try {
arr1.add("hello");
}catch (IndexOutOfBoundsException e){
System.out.println("索引越界");
}
System.out.println(arr.get(0));//hello
}
4.4、如果try中遇到了问题,那么try下面的其他代码还会执行吗?
不会,会直接生成异常对象交给catch捕获。
五、异常常见方法
异常常见有三种方法,这三种方法都是定义在Throwable
类当中的。
public static void main(String[] args){
List<String> arr = new ArrayList<String>();
arr.add("hello");
List<String> arr1 = null;
try {
arr1.add("hello");
}catch (NullPointerException n){
String message = n.getMessage();
System.out.println("n.getMessage():"+message);//null
String s = n.toString();
System.out.println("n.toString():"+s);//java.lang.NullPointerException
n.printStackTrace();//java.lang.NullPointerException at test.main(test.java:16)
}
}
以上方法都不会停止JVM的运行
六、抛出异常
抛出异常有两个关键字 thorws
与 thorw
throws
:写在方法定义处,表示声明一个异常。告诉调用者,使用本方法可能会有哪些异常
thorw
:写在方法内,结束方法;手动抛出异常对象,交给调用者;方法中下面的代码不再执行了