Thinking in java: 通过异常来处理错误(1)

抛出异常的作用

  • 通过规定某种必须保证的形式来防止随心所欲的编程导致的问题,降低处理代码错误的复杂度。
  • 异常是对一种“知道这么做不对,但是代码无法立马解决的”情况的描述
  • 异常将每件事都当做一个事务,作为每个事务的底线维护它们的逻辑稳定性。
  • 一旦异常发生,就不允许程序按照正常模式执行下去。

基本异常

  • 使用throw 抛出异常对象的引用,异常对象的名字一般以Exception结尾
  • 抛出异常之后,会发生什么?
    • 使用new在堆上创建异常对象
    • 停止当前执行路径,抛出异常对象的引用
    • 异常机制接管程序,在异常处理程序中继续管理的运行,然后使程序要么换个方式继续运行,要么继续运行
  • 例子
	if(t == null) throw new NullPointerException();

异常参数

  • 异常对象的根类:Throwable,一般情况下,异常的错误信息可以保存在异常对象的内部,明显的错误也可以通过对象的特定名字来表示
  • 虽然throw方法和return方法在语义上有些相似,都是退出某个作用域,并返回一个对象,但是return返回的是函数压栈的起始位置,而throw则是不确定的,可能会跨越方法的栈

异常捕获

  • try+catch(CatchType catchid),一个try可以抛出多种异常,但是一个catch只能接受一种,因此一个try可以带一系列的catch
	try{
		//method...
	}catch(Type1 id1){
	}catch(Type2 id2){
	}catch(Type3 id3){
	}

终止模型与恢复模型

  • 终止模型:异常错误很关键,程序无法再返回到异常发生的地方继续
  • 恢复模型:
    • 不抛出异常,在发现异常的时候,调用方法修复
    • try...catch放到while循环中,直到没有异常。这会导致代码耦合程度高,让开发人员承担维护人员的职责。

创建自定义异常

  • 异常类只能通过继承实现
  • 在抛出异常的方法名字后面要加上throws xxxException的关键字,这代表着在抛出异常之后,该程序还能继续往下执行(一定要继续往下,因为还没有到catch的位置)
class SimpleException extends Exception{}
public class InheritingException{
	public void f() throws SimpleException{System.out.println("Throw SimpleException from f()");}
	throw new SimpleException();
}
public static void main(String[] args){
	InheritingExceptions sed = new InheritingExceptions();
	try{
		sed.f();
	}catch(SimpleExceptions e){
		System.err.println("Caught it!");
	}
}
  • 对于大多数异常对象来说,最重要的是类的名字,因此很多自定义的异常其实相当于一个重命名
  • 异常调用的printStackTrace(object o)方法可以将从方法调用处到异常抛出处的方法调用序列

异常与记录日志

  • java.util.logging 例子
package com.exception;

import java.util.logging.*;
import java.io.*;
class LoggingException extends Exception{
    private static Logger logger = Logger.getLogger("LoggingException");
    public LoggingException(){
        System.out.println(123);
        StringWriter trace = new StringWriter();
        printStackTrace(new PrintWriter(trace));
        logger.severe(trace.toString());
    }
}
public class LoggingExceptions {
    public static void main(String[] args) {
        try {
            throw new LoggingException();
        }catch(LoggingException e){
            System.err.println("Caught "+ e);
        }
    }
}

  • Logger对象会将接收到的信息发送给System.err,想要获取printStackTrace()的内容,我们可以通过io类中的PrintWriter对象来接受printStackTrace中的信息,然后通过logger.xxx的方法来写入到日志中。
  • 当然,异常类也可以当做普通类来进行扩展,如下所示
	class MyException2 extends Exception{
		private int x;
		public MyException2(){}
		public MyException2(String msg){super(msg);}
		public MyException2(String msg, int x){
			super(msg);
			this.x = x;
		}
		public int val(){
			return x;
		}
		public int String getMessage(){
			return "Detail Message: "+x+" "+super.getMessage();
		}
	}
	public class ExtraFeatures{
		public static void f() throws MyException2{
			print("Throwing MyException2 from f()");
			throw new MyException2();
		}
		public static void g() throws MyException2{
			print("Throwing MyException2 from g()");
			throw new MyException2("Originated in g");
		}
		public static void h() throws MyException2{
			print("Throwing MyException2 from h()");
			throw new MyException2("h");
		}
	}

参考

  • 《JAVA编程思想》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值