Java之异常处理(Exception)
参考:TIJ
最近由于项目的需要,为了写一个稳健的系统,花了将近一天的时间重新学些了java的Exception机制.
因为的Java的主要目标就是发展可供他人使用的程序组件,如果想要构筑一个稳固的系统,每一个组件就必须都要强固才行.
Java的异常处理语言格式
try
{
//可能产生异常的代码
}
catch(ExceptionType1 et)
{
//处理这种异常
}
catch(ExceptionType2 et)
{
//处理这种异常
}
//etc….
finally
{
//一定会执行的动作,经常用来进行一些清理工作,不一定非要写
}
编写自己的异常类
package javaexception;
//演示了如何书写自己的异常
class MyException2 extends Exception
{
private int i;
public MyException2()
{
}
public MyException2( String msg)
{
super(msg);
}
public MyException2(String msg,int j)
{
super(msg);
i=j;
}
public int returnInteger()
{
return i;
}
}
class ExtraFeatures
{
public void f() throws MyException2
{
System.out.println("Throwing MyException2 from f()");
throw new MyException2();
}
public void g() throws MyException2
{
System.out.println("Throwing MyException2 from g()");
throw new MyException2("orginated in g()");
}
public void h() throws MyException2
{
System.out.println("Throwing MyException from h()");
throw new MyException2("originated from h()",23);
}
public static void main(String [] args)
{
ExtraFeatures ef = new ExtraFeatures();
try
{
ef.f();
}
catch(MyException2 e)
{
e.printStackTrace(System.err);
}
try
{
ef.g();
}
catch(MyException2 e)
{
e.printStackTrace(System.err);
}
try
{
ef.h();
}
catch(MyException2 e)
{
e.printStackTrace(System.err);
System.out.println("e.returnInteger()="+e.returnInteger());
}
}
}
如何捕捉所有的异常
由于所有异常的基本型别均为Exception(异常的基本型别并非只是这一个,但是将Exception视为最终根本,对于所有的编程行为都是中肯的)捕捉所有的异常.
catch(Exception e)
{
System.out.println(“Caught an exception”);
}
应该将其置于所有的处理程序的最末端,以免抢去其后的所有的异常处理函数的机会.
异常中函数的使用方法演示
package javaexception;
//此例用来演示Exception的各种method如何运用
class ExceptionMethods
{
public static void main(String [] args)
{
try
{
throw new Exception("This is a Exception");
}
catch(Exception e)
{
System.err.println("Caught Exception");
System.err.println("e.getMessage"+ e.getMessage());
System.err.println("e.getLocalizedMessage" + e.getLocalizedMessage());
/*
Exception 的toString函数
public String toString() {
String s = getClass().getName();//获取class的name
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}
*/
System.err.println("e.toString " + e.toString());
System.out.println("e.printStackTrac)()");
e.printStackTrace(System.err);
}
}
}
重掷异常
有时候你需要重掷异常,将异常重新掷出,会将该异常移动到另一个更高层的context的处理函数去.同一个try block
内的后续其他的catch子句则被忽略不计.此外,其异常的所有内容就会保留,因此上层context内的异常处理函数便会对此异常进行处理.
如果你只是单纯的掷出当前捕捉到的异常,那么使用printStackTrace函数印出的消息便会相应与异常的起始源头,而非异常的重新掷出点,如果你想要设立新的StackTrace信息,你可以是使用函数fillInStackTrace(),它会将目前的stack信息填入旧的异常类内,然后返回对象.
package javaexception
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("thrown from f()");
}
public static void main(String[] args)
throws TwoException {
try {
f();
} catch(OneException e) {
System.err.println(
"Caught in main, e.printStackTrace()");
e.printStackTrace(System.err);
throw new TwoException("from main()");
}
}
} ///:~
异常的局限性
当你override某个函数时,只能够掷出它在base class 中明白列出(即列于异常规格中)的异常.具体一点就是:在派生类的
与基类相对应的函数中,异常的个数要少于或者等于基类所掷异常的个数,或者是基类所掷异常的子类.这是一个很好的限制,因为这意味着可在基类运行的程序代码(包括异常)都能自动在所有衍生的class objects上身上运行,这是基本的oop观念.
下面给出一个实例
package javaexception;
class BaseballException
extends Exception
{}
class Foul
extends BaseballException
{}
class Strike
extends BaseballException
{}
abstract class Inning
{
Inning() throws BaseballException
{
System.out.println("Inning constructor");
}
void event() throws BaseballException
{
// Doesn't actually have to throw anything
}
abstract void atBat() throws Strike, Foul;
{
System.out.println("Inning class atBat");
}
void walk()
{} // Throws nothing
}
class StormException
extends Exception
{}
class RainedOut
extends StormException
{}
class PopFoul
extends Foul
{}
interface Storm
{
void event() throws RainedOut;
void rainHard() throws RainedOut;
}
public class StormyInning
extends Inning implements Storm
{
// OK to add new exceptions for
// constructors, but you must deal
// with the base constructor exceptions:
StormyInning() throws RainedOut,
BaseballException
{
System.out.println("StormyInning constructor");
}
StormyInning(String s) throws Foul,
BaseballException
{}
// Regular methods must conform to base class:
//!void walk() throws PopFoul {} //Compile error
// Interface CANNOT add exceptions to existing
// methods from the base class:
//! public void event() throws RainedOut {}
// If the method doesn't already exist in the
// base class, the exception is OK:
public void rainHard() throws RainedOut
{}
// You can choose to not throw any exceptions,
// even if base version does:
public void event()
{}
// Overridden methods can throw
// inherited exceptions:
void atBat() throws PopFoul
{
System.out.println("StormyInning class atBat");
}
public static void main(String[] args)
{
try
{
StormyInning si = new StormyInning();
si.atBat();
}
catch (PopFoul e)
{
System.err.println("Pop foul");
}
catch (RainedOut e)
{
System.err.println("Rained out");
}
catch (BaseballException e)
{
System.err.println("Generic error");
}
// Strike not thrown in derived version.
try
{
// What happens if you upcast?
Inning i = new StormyInning();
i.atBat();
// You must catch the exceptions from the
// base-class version of the method:
}
catch (Strike e)
{
System.err.println("Strike");
}
catch (Foul e)
{
System.err.println("Foul");
}
catch (RainedOut e)
{
System.err.println("Rained out");
}
catch (BaseballException e)
{
System.err.println(
"Generic baseball exception");
}
}
} ///:~
程序的结果不好理解(没有整明白)
//应该先调用构造函数呀,为什么先是atBat?
Inning class atBat
Inning constructor
StormyInning constructor
StormyInning class atBat
Inning class atBat
Inning constructor
StormyInning constructor
StormyInning class atBat
下面谈谈异常规则的构造思想:
虽然异常规格在继承过程中有编译器强迫施行,但是异常规格并非函数型别的一部分.函数型别仅有其名称和引数(个数和型别)组成,即你无法只靠异常规格的差异进行重载.此外对函数而言,base class 版本既有的异常规格并不意味着必然发生于derived class 版本上.这和继承规则有着极大的不同.换个方式来看,某个函数的”异常规格接口”在继承和override的过程中可能变窄,不可能变宽.而这恰好和class接口在继承过程中规则相反.
对于构造函数不在此列,由于构造函数不属于override,其异常规格是越来越宽的.
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=571339