1.异常是什么?
首先异常(Exception)和错误(Error)并不能划等号,顾名思义,它只是程序运行出现了不正常的情况,
2.异常的家族
从图中我们可以看出Error和Exception属于一个家族的两兄弟,Exception中又分为两类,分别为RuntimeException和非RuntimeException。
解释:
1.Error:这是个严重的问题,但可以不用管它,因为它不是程序本身可以处理的。
2.Exception:异常类,这是程序分内的事了,搞不定就完犊子。
3.非RuntimeException:顾名思义,不是在运行的时候出现的异常,那就是在编译时出现的,不解决了连运行都别想,有些编译器会主动提供解决方案。
4.RuntimeException:千辛万苦可以运行了,数组越界,输入输出格式等问题又开始出现,必须修改程序,解决异常。
3.异常示例
如下新建Demo类:
public class Demo {
public static void main(String[] args) {
String str=1;
}
}
编译无法通过,因为String类型的str我赋值了int型,这是非RuntimeException。
修改代码如下:
public class Demo {
public static void main(String[] args) {
int[]a={1,2,3,4};
System.out.println(a[4]);
}
}
编译没有任何问题,运行时出现异常,因为数组访问最多到a[3],我访问了a[4]。此异常为RuntimeException,运行后控制台出现以下信息。
出现的异常名为ArrayIndexOutOfBoundsException,感兴趣可以去帮助文档中详细查看该异常。该异常出现在Demo.java的第6行。
4.Java虚拟机异常默认处理方案
修改Demo类:
public class Demo {
public static void main(String[] args) {
int[]a={1,2,3,4};
System.out.println("程序开始");
System.out.println(a[4]);
System.out.println("程序结束");
}
}
在出现问题的代码行上增加输出“代码开始”,下增加一行输出“程序结束”,结果如下:
未输出“程序结束”。
总结: JVM默认处理方式为将异常的信息以及位置输出打印,同时程序立刻停止执行。
5.人为处理异常
5.1 try-catch方式
基本格式:
try{
//可能有问题的代码
}catch(异常类名 变量名){
//异常处理代码
}
将可能出现问题的代码写入try中,如果出现异常,会生成一个异常的对象e,被catch后,执行catch中的代码,如果没有异常,不执行catch中的代码。
将上面有异常的Demo类修改如下:
public class Demo {
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4 };
System.out.println("程序开始");
try {
System.out.println(a[4]);
} catch (Exception e) {
System.out.println("访问的数组越界");
}
System.out.println("程序结束");
}
}
执行结果:
特别说明: 因为Exception为RuntimeException的父类,所以catch(Exception e)
不会产生问题,但实际中一段程序可能产生多种异常,最好进行细分,如这里的
catch(ArrayIndexOutOfBoundsException e)
,然后进行数组越界处理。
5.2 throws方式
基本格式:
方法名()throws 异常名{}
这个方式与其说是解决异常,不如说是转移异常,就好像现在的文明灯塔美利坚,股市崩溃了,就玩命印钞撒钱,剪全世界羊毛,只要你用美元,就得给他解决问题。同样,throws并没有真正解决问题,它只是把异常向外抛。谁调用谁解决,调用的人还得用try-catch方法解决异常。似乎很鸡肋,但实际中有时候并不是所有异常都可以自己解决的,比如缺少相关权限。
运用实例:
如下修改Demo类:
public class Demo {
public static void accessElem() throws ArrayIndexOutOfBoundsException {
int[] a = { 1, 2, 3, 4 };
System.out.println(a[4]);
}
public static void main(String[] args){
accessElem();
}
}
运行结果:
显然问题没解决,如下修改Demo类
public class Demo {
public static void accessElem() throws ArrayIndexOutOfBoundsException {
int[] a = { 1, 2, 3, 4 };
System.out.println(a[4]);
}
public static void main(String[] args){
try{
accessElem();
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组访问越界");
}
}
}
运行结果:
main方法调用accessElem方法,但还需要自己解决。
6.自定义异常
异常归根结底都是异常类,我们现在可以直接运用的异常,比如上面的ArrayIndexOutOfBoundsException异常都是前人写的,基本上我们目前能遇到的异常都可以在Java的类库中找到。但是如果真的没有呢?那么我们也可以自己写。
比如我现在要定义一个异常,叫VeryHandsomException。类如下:
public class VeryHandsomException extends Exception {
public VeryHandsomException() {
// 无参构造
}
public VeryHandsomException(String message) {
super(message);
// 带参构造
}
}
message 参数可以通过进入super关键字,追根溯源查看。
Demo类如下:
public class Demo {
public static void accessElem() throws VeryHandsomException {
throw new VeryHandsomException();// 自己写的异常需要手动抛
}
public static void main(String[] args) {
try {
accessElem();
} catch (VeryHandsomException e) {
System.out.println("阁下帅的异常");
}
}
}
运行结果: