0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java异常——捕获异常+再次抛出异常与异常链 的相关知识;
1.1)如果某个异常发生的时候没有再任何地方进行捕获, 那程序就会运行终止: 并在控制台上打印出异常信息 , 其中包括异常的类型堆栈的内容;
1.2)要想捕获一个异常, 必须设置 try/catch 语句块:
1.3)看个荔枝: (看一个读取文本的程序代码以演示捕获异常的处理过程)
public void read(String filename)
{
try
{
InputStream in = new FileInputStream(filename); // 创建输入流
int b;
while((b=in.read()) != -1)
process input
}
catch(IOException exception)
{
exception.printStackTrace(); // 打印栈轨迹;
}
}
对上述代码的分析(Analysis):
1.4)对于一个普通 的程序来说, 处理以上的对异常处理的方法外,还有其他方法吗?
public void read(String filename) throws IOException
{
InputStream in = new FileInputStream(filename); // 创建输入流
int b;
while((b=in.read()) != -1)
process input
}
Attention)编译器严格地执行 throws 说明符。 如果调用了一个抛出已检查异常的方法, 就必须对它进行处理, 或者将它继续进行传递;
1.5)对于以上两种处理异常的方法, 哪种 方法更好呢?(method1:自己处理(在可能发生异常的函数中添加try/catch 语句块);method2:将异常传递(throw)给调用者,调用者处理)
Attention)以上规则有个例外: 前面提到, 如果编写一个 覆盖超类的方法, 而这个方法又没有抛出异常, 那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的 throws 说明符中出现超过超类方法所列出的异常类范围;(也就是说父类方法没有抛出异常,你子类方法也不准抛出异常,只能自己添加 try/catch 语句块自己处理)
2.1)在一个try 语句块中可以捕获多个异常, 并对不同类型的异常做出不同的处理。可以按照下列方式为每个异常类型使用一个单独的 catch 子句;
try
{}
catch(FileNotFoundException e)
{}
catch(UnknownHostException e)
{}
catch(IOException e)
{}
2.2)要想获得异常对象 的更多信息: 可以试着使用 e.getMessage() 得到详细的错误信息, 或者使用 e.getClass().getName(); 得到异常对象 的实际类型;
2.3)合并catch 子句: 在 java SE7中, 同一个 catch 子句中可以捕获多个异常类型。 例如, 假设对应缺少文件和 未知主机异常的动作是一样的, 就可以合并catch 子句:
try
{}
catch(FileNotFoundException | UnknownHostException e)
{}
catch(IOException e)
{}
Attention)
3.1)在catch子句中可以抛出一个异常, 这样做的目的是 改变异常类型;
try
{}
catch(SQLException e)
{
throw new ServletException("data error : " + e.getMessage());
}
对以上代码的分析(Analysis):
try
{}
catch(SQLException e)
{
Throwable se = new ServletException("database error");
se.initCause(e);
throw se;
}
Throwable e = se.getCause();
Attention)强烈建议使用这种包装技术, 这样可以让用户抛出子系统中的高级异常, 而不会丢失原始异常的小细节; (推荐使用 strongly recommended)
Hint)
try
{
access the database
}
catch(Exception e)
{
logger.log(level, message, e);
throw e;
}
public void updateRecord() throws SQLException