java基础之通过异常处理错误

 

        

        我们在编程过程中,通常需要时刻关注可能遇到的问题,此时可以把问题分为两类:普通问题与异常问题。普通问题:我们可以通过从当前环境中获取到的信息来解决这个问题;而异常问题:在当前环境中获取到的信息并不能解决这个问题,所以我们阻止了程序的执行,跳出当前的环境,将这个异常问题,抛到上一级的环境中去解决。可以看出异常机制存在两种基本模型:终止模型(假设异常非常的关键,程序无法自我修复)和恢复模型(可以通过异常处理程序,调用相应的方法来修复出现的错误),然而我们现在所见到的基本为终止模型。

        如果方法内部出现了异常,方法将在抛出异常的过程中终止。我们可以通过try建立监控区,在出现异常时跳转到catch区让方法继续执行。我们在编程过程中,关注的重点常在于异常的名字,所以我们可以定义自己需要的异常,此时只需要继承Exception类即可,例如:

public class LogingException extends Exception{
	private static final long serialVersionUID = 1L;
	
	private static Logger logger = Logger.getLogger("LoggingException");
	
	public LogingException(){
		StringWriter trace = new StringWriter();
		printStackTrace(new PrintWriter(trace));
		logger.severe(trace.toString());
	}
}

        我们实现在一个异常,同时重载了printStackTrace()方法,增加了一个新的功能,在抛出异常时可以自动记录日志。printStackTrace()方法会打印Throwable和Throwable的调用栈轨迹,我们可以通过getStackTrace()获取printStackTrace()所提供的信息,会返回一个由栈轨迹中的元素所构成的数组,元素0为栈顶元素,为调用序列中的最后一个方法的调用;最后一个元素为栈底元素,为调用序列中的第一个方法的调用。我们也可以在catch中将异常重新抛出,此时printStackTrace()显示的为原来的异常抛出点的调用栈信息,如果想显示重新抛出点的信息,可以先调用fillInStackTrace()方法,但此时原来异常抛出点的调用栈信息会丢失。

      如果我们也需要显示原始异常的信息该怎么做呢?Throwable的构造方法中其中一个就是介绍cause对象作为参数,cause表示原始异常,可以将原始异常传递给新的异常。在出现异常时,可以通过这样的异常链追踪到异常的最初位置,这也是为什么我们调试异常时先从最下面开始看起。

      如果我们在方法中抛出异常时,Java强制我们礼貌的告诉别人某个方法可能会抛出的异常类型,这样别人在调用这个方法时就可以作相应的处理,这就是异常说明,通过关键字throws来实现,它属于方法声明的一部分。在Java的继承关系中关于异常由以下几个需要注意的点:

     ①如果父类某个非构造方法抛出了异常,那么子类相应的方法只能抛出基类方法中列出的那些异常或异常派生出的异常。

     ②对于构造方法则恰恰相反,子类构造方法必须抛出包含父类构造方法所抛出的异常,这是由于子类通常需要调用父类的构造方法进行初始化。

     ③虽然编译器对异常说明做了强制要求,但是异常说明并不属于方法类型一部分,所以就不要想着能通过抛出不同的异常来重载方法了。

     ④在catch方法对异常类型进行匹配时,catch中的参数exception会匹配该异常类及其子类,匹配成功后,java会认为异常得到了处理,就不在继续向下查找了,这点和以前所学的switch不同,没有break之类的。这点非常重要,如果你修改程序方法,抛出了跟具体派生异常,别人并不需修改代码也可以捕获该异常。例如:

class Annoyance extends Exception{};

class Sneeze extends Annoyance{};

public class Human {
	public static void main(String[] args) {
		try{
			throw new Annoyance();
		}catch(Sneeze s){
			System.out.println("Caught Sneeze");
		}catch(Annoyance a){
			System.out.println("Caught Annoyance");
		}
		
		try{
			throw new Sneeze();
		}catch(Annoyance a){
			System.out.println("Caught Annoyance");
		}
//		catch(Sneeze s){
//			System.out.println("Caught Sneeze");
//		}
	}
}

        java中还存在一类比较特殊的异常RuntimeException(常见到的NullPointerException就属于它),这属于运行时异常,编译器不对异常声明进行强制检查。这也能给我带来很多的便利,我们可以不用写try/catch或异常声明,如果出现异常,会自动沿着调用栈向上冒泡。也可以通过前面提到的异常链,使用RuntimeException包装强制检查的异常,然后通过getCause()捕获特定的异常。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值