C++、Java和C#中的异常处理

来源:温少的日志

C++中异常:
1、可以抛出任何异常。虽然标准C++定义了std::exception类,但throw的对象可以是任何对象。包括int、char*等。例如:

throw   100 ;

try   {
 
// do something 
}
  catch  ( int  num)  {
 
// do something 
}

但是,C++标准库中抛出的所有异常,都是派生自std::exception类。
std::exception定义如下:

class  exception  {
    
public:
        exception( );
        exception(
const char *const&);
        exception(
const char *const&int);
        exception(
const exception&);
        exception
& operator=(const exception&);
        
virtual ~exception( );
        
virtual const char *what( ) const;
}
;


2、标准C++中,是没有finally子句。熟悉Java和C#的朋友,也许会觉得奇怪!没有finally子句,使用的确不方便。

3、C++中,函数的声明,缺省时可以抛出任何异常的,也可以使用异常规范来约束函数抛出的异常,如:

// 可以抛出任何异常
void  f()  {
 
throw 100;
}


// 描述该函数不会抛出任何异常
void  f()  throw ()  {
}


// 描述该函数会抛出int或者char*类型的异常
void  f()  throw ( int char * {
    
// do something 
}

但是,C++中的异常规范不是很可靠。如下的代码也是可以编译通过的,但是编译器会给出警告。

void  f()  throw ( int char * {
    
throw "100";
}


4、C++的异常可以派生自多个异常基类。这一个特性使得难以分类的异常容易处理,例如网络文件的异常:

class  file_exception  {}
class  network_exception  {}
class  newwork_file_exception :  public  file_exception,  public  network_exception  {}


5、捕捉所有异常的语法。C++中,不是单根继承的,所以你不能,如同Java或者C#那样,通过捕捉某个基类来捕捉所有的异常。

try   {
 
// do something 
}
  catch  ( //捕捉所有的异常
 
// do something 
}

总结,C++中,命名空间和异常规范是作为针对大规模程序设计而引入的特性。但是由于C++中没有垃圾收集机制,异常造成了资源管理变得非常复杂。在C++中,编写异常安全的代码,是十分困难的。



Java中的异常:

1、可以抛出任何派生自了Throwable的类。Throwable类的定义如下:

public   class  Throwable implements Serializable  {
 
public Throwable();
 
public Throwable(String message);
 
public Throwable(String message, Throwable cause); //@since  1.4
 public Throwable(Throwable cause); //@since  1.4
 public String getMessage();
 
public String getLocalizedMessage(); //@since   JDK1.1
 public Throwable getCause(); //@since 1.4
 public synchronized Throwable initCause(Throwable cause); //@since  1.4
 public String toString();
 
public void printStackTrace();
 
public void printStackTrace(PrintStream s);
 
public void printStackTrace(PrintWriter s); //@since   JDK1.1
 private void printStackTraceAsCause(PrintWriter s,
                                        StackTraceElement[] causedTrace);
 
public synchronized native Throwable fillInStackTrace(); 
  
public StackTraceElement[] getStackTrace(); //@since  1.4
  public void setStackTrace(StackTraceElement[] stackTrace); //@since  1.4
}

Throwable下分Exception和Error。

public   class  Exception extends Throwable  {}
public   class  Error extends Throwable  {}

而Exception中,有一个特别的派生类,RuntimeException,如下:
public class RuntimeException extends Exception {}
类图如下:


Java divides exceptions in two categories: checked exceptions and unchecked exceptions. Exceptions that are not "checked" by the compiler are called unchecked exceptions; exceptions that are "checked" by the compiler are called checked exceptions. The compiler will not compile a file if it contains a method where a checked exception may occur and the method does not handle the checked exception in a catch block or list it in the method header. The classes RuntimeException, Error and their subclasses are unchecked exceptions. All other exception classes are checked exceptions.

If a checked exception might occur in a method and the method does not have catch block to handle the checked exception, then the checked exception must be declared in the method header using a throws clause. For example, if an IOException might occur in method readInteger and readInteger doesn't handle it, then readInteger must have the following header:

public int readInteger() throws IOException {

}

If readInteger does not list IOException in its throws clause, compilation will fail with an error message about checked exceptions. Unchecked exceptions may be listed in a throws clause, but the compiler does not require it.

In the following code, neither method readInteger nor method main( ) catches IOException so they both list IOException in their throws clauses. When method main throws an IOException, the exception object is passed to the Java Virtual Machine (JVM). The JVM displays the exception information and terminates the program.

 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
import java.io.*;

/**
* This class provides a method that reads an integer from the
* standard input.
*
* @author author name
* @version 1.0.0
*/
public class IntegerReaderThrowsException {

private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));

private static PrintWriter stdErr =
new PrintWriter(System.err, true);

private static PrintWriter stdOut =
new PrintWriter(System.err, true);

/**
* Tests method <code>readInteger</code>
*
* @param args not used
* @throws IOException if error reading from standard input.
*/
public static void main (String[] args) throws IOException {

stdOut.println("The value is: " + readInteger());
}

/**
* Reads an integer from the standard output.
*
* @return the <code>int</code> value.
* @throws IOException if error reading from standard input.
*/
public static int readInteger() throws IOException {

do {
try {
stdErr.print("Enter an integer> ");
stdErr.flush();

return Integer.parseInt(stdIn.readLine());

} catch (NumberFormatException nfe) {
stdErr.println("Invalid number format");
}
} while (true);
}
}
Listing 4 IntegerReaderThrowsException.java

2、 Java中,也使用异常规范,并且在整个基础类库中都使用。Java是基于JVM运行,但是JVM本身就抛出异常,也就是,所有的方法都可能抛出异常。因 此,Java编译器编译不检查Error和RuntimeException。与C++不同,没有异常规范,缺省不允许抛出任何非 RuntimeException和Error的异常。如下:

public   void  f()  {
 
throw new RuntimeException(); //正确
}


public   void  f()  {
 
throw new Error(); //正确
}

以下的代码编译出错

public   void  f()  {
 
throw new Exception(); 
}

使用异常规范的正确例子:

public  WfException extends Exception  {}

public   void  f() throws WfException  {
 
throw new WfException();
}


3、Throwable、Exception、RuntimeException中部分成员,是在不同的JDK版本中添加的,编写代码的时候需要注意。如下的代码不能在JDK 1.3中编译通过:

public   void  f() throws WfException  {
 
try {
  
// do something 
 }
 catch (Exception e) {
  
throw new WfException ("", e);
 }

}


4、Java中的try语法,包括finally子句。如下:

try   {
 
// do something 
}
  catch  (Exception e)  {
 
// do something 
}
  finally   {
 
// do something 
}

 

C#中的异常:
1、C#异常的局限性。C#是基于CLR运行的,由于CLR需要支持多种语言,其异常的 实现受到了较大的局限。一个重要的特征就是没有异常规范,很多人对此很失望!Anders Hejlsberg曾专门发表过文章,说明为什么C#不支持异常规范,说得也很有道理。但是,没有异常规范的C#,变得简单,但也更容易犯错误,在这一点 上,我更喜欢Java,而不喜欢C#的方式。没有异常规范,编译器就不会帮我们检查代码,是否做了try ... catch处理。

2、异常的结构。在.NET Framework中,所有的异常派生自System.Exception基类。其下有两个子类:SystemException和 ApplicationException。自行编写异常类,不建议直接派生自Exception类,而是应该派生自 ApplicationException。

3、C#犹如Java,也支持finally的写法。如:

try  
{
 
// do something 
}
 
catch  (Exception e) 
{
 
// do something 
}
 
finally  
{
 
// do something
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值