Throwable:所有异常的父类。
error:直译的意思是错误,这种错误是虚拟机的错误,例如:系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。这类错误是代码无能为力的,所以不用捕捉。
exception:直译的意思是意料之外,异常。是指编译时逻辑上的错误,应该捕获并且处理的。
RuntimeException,也就是运行时异常,表示你的代码本身存在BUG,比如你提到的ArrayIndexOutOfBoundsException,数组下标越界,这个属于代码有问题,数组定义的长度不够实际使用,不处理肯定会报错,如果你操作某个模块发现能正常运行,那只是因为代码还没跑到这个错误的地方而已。。控制台一旦报RuntimeException,就必须要处理。。没有例外的。而且,处理RuntimeException,不是try-catch能解决的。。try-catch在这里使用毫无意义,这种错误是不需要强制捕获的。
不是RuntimeException,就是编译时异常,异常只有这两种了。比如你在处理文件流时的I/O问题,就属于编译时异常。这个时候用thr{}catch 来捕获或者 throws即可,一般编译器都会有提示,这种错误是需要强制捕获的。
关于捕获异常的使用:
异常的捕获一般是用三种方式:try-catch(或者try-catch-finally),throws,throw。
1.注意捕获的异常要子类要写在前面,如:
try {
System.out.println("ssss");
} catch (UnsupportedEncodingException e) {
System.out.println("");
} catch (IOException e){
System.out.println("");
} finally {
System.out.println();
}
也可以同时捕获多个异常,如:
try {
System.out.println("ssss");
} catch (IOException | NumberFormatException e){
System.out.println("");
} finally {
System.out.println();
}
2.抛出异常-throw,终止程序并抛出异常:
public static void main(String[] args) {
throw new IllegalArgumentException("1");
throw new RuntimeException("2");
throw new IOException("3");
}
2.1异常转换问题,如:
public static void main(String[] args) {
process1("");
}
public static void process1(String s) {
try {
process2(s);
} catch (NullPointerException e) {
// TODO Auto-generated catch block
throw new IllegalArgumentException();
}
}
public static void process2(String s) {
throw new NullPointerException();
}
这样的话新的抛出的异常会覆盖掉原先的异常,影响寻找第一个异常的出处,正确的方法是把原有的异常传入到新的异常中:
public static void main(String[] args) {
process1("");
}
public static void process1(String s) {
try {
process2(s);
} catch (NullPointerException e) {
throw new IllegalArgumentException(e);//here is changed
}
}
public static void process2(String s) {
throw new NullPointerException();
}
2.2 异常屏蔽问题
public static void main(String[] args) {
try {
process1("");
} catch (Exception e) {
System.out.println("catched");
throw new RuntimeException("catched error");
} finally {
System.out.println("finally");
//throw new RuntimeException("finally error");
}
}
private static void process1(String s){
throw new IllegalArgumentException();
}
当finally不抛出异常的时候,会先输出catch里面的值,然后输出finally里面的值,最后抛出catched里面的异常,其结果为:
catched
finally
Exception in thread "main" java.lang.RuntimeException: finally error
at com.Exceptions.main(Exceptions.java:12)
当finally抛出异常的时候,会覆盖掉catch里面的异常,执行顺序以及输出结果为:
catched
finally
Exception in thread "main" java.lang.RuntimeException: finally error
at com.Exceptions.main(Exceptions.java:12)
2.3 异常的存储问题
public static void main(String[] args) {
Exception origin = null;
try {
process1("");
} catch (Exception e) {
origin = e;
throw new RuntimeException(e);
} finally {
try {
throw new NullPointerException();
} catch (Exception e) {
if (origin != null) {
origin.addSuppressed(e);
} else {
origin = e;
}
}
if (origin != null) {
throw origin;
}
}
}
private static void process1(String s) {
throw new IllegalArgumentException();
}
3.自定义异常
自定义异常其实就是自定义控制台报异常的打印,对于异常类型的捕捉还是有区别的,例如:
package com;
public class MyThrow extends Exception{
public MyThrow() {
super();
// TODO Auto-generated constructor stub
}
public MyThrow(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
package com;
public class ChainTest {
public static void main(String[] args) {
ChainTest ct = new ChainTest();
ct.test2();
}
public void test1() throws MyThrow {
throw new MyThrow("喝酒别开车!");
}
public void test2() {
try {
test1();
} catch (MyThrow e) {
RuntimeException newExc = new RuntimeException("司机一滴酒,亲人两行泪~~");
newExc.initCause(e);
throw newExc;
}
}
}
控制台打印为:
Exception in thread "main" java.lang.RuntimeException: 司机一滴酒,亲人两行泪~~
at com.ChainTest.test2(ChainTest.java:24)
at com.ChainTest.main(ChainTest.java:13)
Caused by: com.MyThrow: 喝酒别开车!
at com.ChainTest.test1(ChainTest.java:17)
at com.ChainTest.test2(ChainTest.java:22)
... 1 more
可以看到,仅仅是报错的信息有所该改变而已。