基本异常
是指阻止当前的方法或者作用域继续执行的问题
普通问题:在当前的环境下能够获得足够的信息,总能处理这个错误,但是异常情形无法获得的必要的信息来解决问题
抛出异常:从当前的环境跳出,把问题提交给上一级环境。
首先,就像创建其他对象一样,先使用new在堆上创建异常对象,然后当前的执行路径被终止。并且从当前的环境中弹出对异常对象的引用,这个时候,异常处理机制接管程序,并且寻找一个恰当的位置来继续执行程序(并不是说异常发生,程序就不会继续执行了)
这个恰当的位置就是异常处理程序,它的任务就是将程序从错误状态中恢复回来,要么程序继续执行,要么换一种方式继续执
异常参数
所有的标准异常类都有两个构造器:一个是默认构造器,另一个是接受字符串作为参数
从效果上看throw就像是从方法中返回的,可以将它看成一种不同的返回机制,另外还可以用抛出异常的方式从当前的作用域退出。
try块
如果在方法内部抛出了异常,这个方法就在抛出异常之后就结束了
如果不希望就此结束,可以在方法内部设置一个try块,来捕获异常,因为这个块里尝试各种方法调用(可能产生异常的),是跟在try后面的普通程序代码块:try{}
异常处理程序catch
抛出的异常必须在某个地点得到处理,这里就是异常处理程序,并且对于每个捕获的异常,都得到相应的处理程序
它紧跟在try块后面,用关键字catch表示
终止和恢复
终止模型:一旦异常被抛出,就会终止程序
恢复模型:通常是异常被处理之后,可以继续程序的运行的(catch中不要throw)
创建自定义异常
要自己定义异常,必须从已有的异常类中继承,而且最好选择意思相近的异常类继承
public class InheritingExceptions {
public void f() throws SimpleException {
System.out.println("Throw SimpleException from f()");
throw new SimpleException(); //异常对象引用
}
public static void main(String[] args) {
final InheritingExceptions i = new InheritingExceptions();
try {
i.f();
} catch (SimpleException e) {
System.out.println("Caught it");
}
}
}
对异常来说,最重要的就是部分就是类名和错误提示
也可以为自定义异常创建一个带参数的构造器
class MyException extends Exception{
public MyException(){}
public MyException(String msg){super(msg);}
}
public class FullConstructor {
public static void f() throws MyException {
System.out.println("Throwing MyException from f()");
throw new MyException();
}
public static void g() throws MyException {
System.out.println("Throwing MyException from g()");
throw new MyException("Originated in g()");
}
public static void main(String[] args) {
try {
f();
} catch (MyException e) {
e.printStackTrace();
}
try {
g();
} catch (MyException e) {
e.printStackTrace();}}}
捕获所有异常
通过只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类Exception,最好将其放在处理程序列表的末尾
栈轨迹
public class WhoCalled {
static void f(){
try {
throw new Exception();
} catch (Exception e) {
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
System.out.println(stackTraceElement.getMethodName());
}
}
}
static void g(){f();}
static void h(){g();}
public static void main(String[] args) {
f();
System.out.println("------------");
g();
System.out.println("------------");
h();
}
重新抛出异常
把刚捕获的异常重新抛出,重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try块的后续catch字句将被忽略。如果只是把当前的异常重新抛出,那么printStackTrace()方法显示的是原来异常抛出点的调用栈信息,而不是重新抛出点的信息
public class ReThrowing {
public static void f() throws Exception {
System.out.println("originating the exception in f()");
throw new Exception("thrown in f()");
}
public static void g() throws Exception {
try {
f();
} catch (Exception e) {
System.out.println("Inside g(),e,printStackTrace()");
e.printStackTrace();
throw e;
}
}
public static void h() throws Exception {
try {
f();
} catch (Exception e) {
System.out.println("Inside h(),e.printStackTrace()");
e.printStackTrace();
throw (Exception) e.fillInStackTrace(); //调用这个方法就成了异常的新发生地
}
}
public static void main(String[] args) {
try {
g();
} catch (Exception e) {
System.out.println("Main,printStackTrace()");
e.printStackTrace();
}
try {
h();
} catch (Exception e) {
System.out.println("Main,printStackTrace()");
e.printStackTrace();
}
}
}
class OneException extends Exception{
public OneException(String s){super(s);}
}
class TwoException extends Exception{
public TwoException(String s){super(s);}
}
public class RethrowNew {
public static void f() throws OneException {
System.out.println("originating the exception in f()");
throw new OneException("throw from f()");
}
public static void main(String[] args) {
try {
try {
f();
} catch (OneException e) {
System.out.println("Caught in inner try, e.printStackTrac()");
e.printStackTrace();
throw new TwoException("from inner try");
}
}
catch (TwoException e){
System.out.println();
e.printStackTrace();
}
} //组后异常仅仅知道自己来自main(),而且对f()一无所知
}
Java标准异常
Throwable这个类可以作为任何异常被抛出的类,它可以分为两种类型
Error:表示编译时和系统错误,一般不需要关心
Exception:是可以被抛出的基本类型,在Java类库,用户方法,或者运行时的故障都可能抛出Exception异常
通常关心的基本类型时Exception
RuntimeException
使用finally进行清理
finally子句总能运行
class ThreeException extends Exception{}
public class FinallyWorks {
static int i = 0;
public static void main(String[] args) {
while (true){
try{
if (i++ == 0){
throw new ThreeException();
}System.out.println("No exception");
}catch (Exception e){
System.out.println("Three Exception");
}finally { //finally语句总能执行
System.out.println("In finally clause");
if (i == 2){
break;
}
}
}
}
}
如果异常抛出了但是没有被捕获,就会出现下种情况
public class Switch {
private boolean state = false;
public boolean read(){return state;}
public void on(){state = true;
System.out.println(this);}
public void off(){state = false;
System.out.println(this);}
@Override
public String toString() {return state ? "on" : "off";}
}
class OnOffException1 extends Exception{}
class OnOffException2 extends Exception{}
public class OnOffSwitch {
static Switch sw = new Switch();
public static void f() throws OnOffException1,OnOffException2{}
public static void main(String[] args) {
try {
sw.on();
f();
//sw.off(); //注掉发现并没有执行下列catch中任何一个off方法
}catch (OnOffException1 e){
System.out.println("OneException1");
sw.off();
}catch (OnOffException2 e){
System.out.println("OneException2");
sw.off();
}
}
}
此时finally的作用就来了
public class OnOffSwitch {
static Switch sw = new Switch();
public static void f() throws OnOffException1,OnOffException2{}
public static void main(String[] args) {
try {
sw.on();
f();
//sw.off();
}catch (OnOffException1 e){
System.out.println("OneException1");
sw.off();
}catch (OnOffException2 e){
System.out.println("OneException2");
sw.off();
}finally { //finally子句总可以运行
sw.off();
}
}
}
甚至异常没有被当前的异常处理程序捕获的情况下,异常处理机制,也会在跳在更高一层的异常处理程序之前,执行finally子句
class FourException extends Exception{}
public class AlwaysFinally {
public static void main(String[] args) {
System.out.println("first");
try {
System.out.println("second");
try {
throw new FourException();
}finally {
System.out.println("2nd");
}
}catch (Exception e){
System.out.println("3rd");
}finally {
System.out.println("4th");
}
}
}
在return中使用finally
public class MultipleReturns {
public static void f(int i){
System.out.println("=====================");
try {
System.out.println("1");
if (i == 1){return;};
System.out.println("2");
if (i == 2){return;}
System.out.println("3");
if (i == 3){return;}
}finally {
System.out.println("Always finally");
}
}
public static void main(String[] args) {
for (int i = 1; i < 4; i++) {
f(i);
}
}
}
缺憾: 异常丢失
class VeryImportantException extends Exception{
@Override
public String toString() {
return " A very important exception";
}
}
class HomuException extends Exception{
@Override
public String toString() {
return "A trivial exception";
}
}
public class LostMessage {
void f() throws VeryImportantException {
throw new VeryImportantException();
}
void g() throws HomuException {
throw new HomuException();
}
public static void main(String[] args) {
try {
LostMessage lm = new LostMessage();
try {
lm.f();
}finally {
lm.g();
}
}catch (Exception e){
System.out.println(e); //VeryImportantException丢失了
}
}
}