程序总会出现异常的,需要我们去处理。C++和JAVA都有自己异常机制,我们应该遵循着去处理异常。那它们的异常机制有何异同呢?
要注意一点:异常机制处理异常是要付出代价的,即异常处理的代码比无异常处理的要慢好多倍。
JAVA的异常机制
在面向对象的世界里,一切都是对象,JAVA的异常也不例外。API中异常类的“始祖”是 Throwable 类,有 Exception 类和 Error 类直接继承Throwable 。Error是很严重的,是不可挽救的,我们一般是通过继承Throwable 或Exception 来定义自己的异常类。
先看看API(这里是从1.5摘抄的)里的两个异常类是怎样的?
public class Throwable implements Serializable ... {
/** *//** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -3042686055658047285L;
/** *//**
* Native code saves some indication of the stack backtrace in this slot.
*/
private transient Object backtrace;
private String detailMessage;
private Throwable cause = this;
private StackTraceElement[] stackTrace;
public Throwable() ...{
fillInStackTrace();
}
public Throwable(String message) ...{
fillInStackTrace();
detailMessage = message;
}
public Throwable(String message, Throwable cause) ...{
fillInStackTrace();
detailMessage = message;
this.cause = cause;
}
public String getLocalizedMessage() ...{
return getMessage();
}
public Throwable getCause() ...{
return (cause==this ? null : cause);
}
public synchronized Throwable initCause(Throwable cause) ...{
if (this.cause != this)
throw new IllegalStateException("Can't overwrite cause");
if (cause == this)
throw new IllegalArgumentException("Self-causation not permitted");
this.cause = cause;
return this;
}
public String toString() ...{
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}
private synchronized StackTraceElement[] getOurStackTrace() ...{
// Initialize stack trace if this is the first call to this method
if (stackTrace == null) ...{
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
}
return stackTrace;
}
//......省略了一些
}
注意一点:异常类是可串行化的。
static final long serialVersionUID = - 3387516993124229948L ;
public Exception() {
super ();
}
public Exception(String message) {
super (message);
}
public Exception(String message, Throwable cause) {
super (message, cause);
}
public Exception(Throwable cause) {
super (cause);
}
}
一个简单例子:
... {
MyException(String str)
...{
super(str);
}
}
public class MyTest
... {
public void f()throws MyException
...{
throw new MyException("f() exception");
}
}
public class Main
... {
public static void main(String[]args)
...{
try
...{
new MyTest().f();
}catch(MyException me)
...{
System.out.println(me);
}finally
...{System.out.println("finally");
}
}
}
如果可能发生多种异常时,可用多个catch语句捕捉不同类型的异常,从第一个catch开始匹配异常,如果异常是该类或该类的子类,则匹配。如果要匹配所有的异常,则在catch中捕捉 Throwable 类,因为其它所有异常类都是其子类,都可匹配。其中 finally块是程序必然会执行的块,除非JVM突然退出了。
C++的异常机制
在C的时候,错误处理要 setjmp() / longjmp() 通过。而C++里, setjmp() / longjmp() 已经不能用了。C++的异常可以是类,也可以是基本类型(如int)。在标准库中,也存在exception类。但是,C++并没有要求我们自定义的异常要继承某个类。
一个简单例子:
using namespace std;
#ifndef NULL
#define NULL 0
#endif
class MyException
... {
const char * const msg;
public:
MyException(const char* const _msg=NULL):msg(_msg)...{};
void print()
...{
cout<<msg<<endl;
}
} ;
void f()
... {
throw MyException("something bad happened");
}
int main()
... {
try
...{
f();
}catch(MyException me)
...{
me.print();
}
system("pause");
return 0;
}
C++的异常捕捉匹配和JAVA的基本相同,只是C++没有 finally 块。要捕捉所有异常的方法是用 catch(...) 语句。
以上所述都只是JAVA和C++的异常机制的皮毛。对JAVA的异常,觉得自己理解得还可以,懂得什么是捕捉,什么是抛出异常、传播异常和包装异常等。但是对C++的异常,可以说是刚刚接触,刚才看了 Thinking in C++ 异常处理的一章。想起JAVA的异常机制,就作个对比,写个笔记。