- 浏览: 71774 次
- 性别:
- 来自: 成都
-
文章分类
最新评论
-
itaxi:
多谢, 一个serialize() 拯救了我
异步提交表单多个应用 -
fengxinsixin:
学习一下,谢谢!
局域网聊天工具(2) -
wecley:
标记,学习~~
局域网聊天工具(2) -
香烟与酒:
您好,把这个js <script src=" ...
Ajax获取数据动态树形节点实现 -
jasstion:
第二个不需要
Ajax获取数据动态树形节点实现
Java异常机制(Good!)
编辑 | 删除 | 权限设置 | 更多▼ 设置置顶
推荐日志
转到私密记事本
阿飞 发表于2009年04月04日 08:45 阅读(2) 评论(0)
分类: 个人日记 权限: 公开
本章介绍Java的异常处理机制。异常(exception)是在运行时代码序列中产生一种异常情况。换句话说,异常是一个运行时错误。在不支持异常处理的计算机语言中,错误必须被手工的检查和处理——典型的是通过错误代码的运用等等。这种方法既很笨拙也很麻烦。Java的异常处理避免了这些问题,而且在处理过程中,把运行时错误的管理带到了面向对象的世界。
10.1 异常处理基础
Java异常是一个描述在代码段中发生的异常(也就是出错)情况的对象。当异常情况发生,一个代表该异常的对象被创建并且在导致该错误的方法中被引发(throw)。该方法可以选择自己处理异常或传递该异常。两种情况下,该异常被捕获(caught)并处理。异常可能是由Java运行时系统产生,或者是由你的手工代码产生。被Java引发的异常与违反语言规范或超出Java执行环境限制的基本错误有关。手工编码产生的异常基本上用于报告方法调用程序的出错状况。Java异常处理通过5个关键字控制:try、catch、throw、throws和 finally。下面讲述它们如何工作的。程序声明了你想要的异常监控包含在一个try块中。如果在try块中发生异常,它被抛出。你的代码可以捕捉这个异常(用catch)并且用某种合理的方法处理该异常。系统产生的异常被Java运行时系统自动引发。手动引发一个异常,用关键字throw。任何被引发方法的异常都必须通过throws子句定义。任何在方法返回前绝对被执行的代码被放置在finally块中。
下面是一个异常处理块的通常形式:
try {
// block of code to monitor for errors
}
catch (ExceptionType1 exOb) {
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb) {
// exception handler for ExceptionType2
}
// ...
finally {
// block of code to be executed before try block ends
}
这里,ExceptionType 是发生异常的类型。下面将介绍怎样应用这个框架。
10.2 异 常 类 型
所有异常类型都是内置类Throwable的子类。因此,Throwable在异常类层次结构的顶层。紧接着Throwable下面的是两个把异常分成两个不同分支的子类。一个分支是Exception。该类用于用户程序可能捕捉的异常情况。它也是你可以用来创建你自己用户异常类型子类的类。在Exception分支中有一个重要子类RuntimeException。该类型的异常自动为你所编写的程序定义并且包括被零除和非法数组索引这样的错误。另一类分支由Error作为顶层,Error定义了在通常环境下不希望被程序捕获的异常。Error类型的异常用于Java运行时系统来显示与运行时系统本身有关的错误。堆栈溢出是这种错误的一例。本章将不讨论关于Error类型的异常处理,因为它们通常是灾难性的致命错误,不是你的程序可以控制的。
10.3 未被捕获的异常
在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的。下面的小程序包括一个故意导致被零除错误的表达式。
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42 / d;
}
}
当Java运行时系统检查到被零除的情况,它构造一个新的异常对象然后引发该异常。这导致Exc0的执行停止,因为一旦一个异常被引发,它必须被一个异常处理程序捕获并且被立即处理。该例中,我们没有提供任何我们自己的异常处理程序,所以异常被Java运行时系统的默认处理程序捕获。任何不是被你程序捕获的异常最终都会被该默认处理程序处理。默认处理程序显示一个描述异常的字符串,打印异常发生处的堆栈轨迹并且终止程序。下面是由标准javaJDK运行时解释器执行该程序所产生的输出:
java.lang.ArithmeticException: / by zero
at Exc0.main(Exc0.java:4)
注意,类名Exc0,方法名main,文件名Exc0.java和行数4是怎样被包括在一个简单的堆栈使用轨迹中的。还有,注意引发的异常类型是Exception的一个名为ArithmeticException
的子类,该子类更明确的描述了何种类型的错误方法。本章后面部分将讨论,Java提供多个内置的与可能产生的不同种类运行时错误相匹配的异常类型。堆栈轨迹将显示导致错误产生的方法调用序列。例如,下面是前面程序的另一个版本,它介绍了相同的错误,但是错误是在main( )方法之外的另一个方法中产生的:
class Exc1 {
static void subroutine() {
int d = 0;
int a = 10 / d;
}
public static void main(String args[]) {
Exc1.subroutine();
}
}
默认异常处理器的堆栈轨迹结果表明了整个调用栈是怎样显示的:
java.lang.ArithmeticException: / by zero
at Exc1.subroutine(Exc1.java:4)
at Exc1.main(Exc1.java:7)
如你所见,栈底是main的第7行,该行调用了subroutine( )方法。该方法在第4行导致了异常。调用堆栈对于调试来说是很重要的,因为它查明了导致错误的精确的步骤。
10.4 使用try和catch
尽管由Java运行时系统提供的默认异常处理程序对于调试是很有用的,但通常你希望自己处理异常。这样做有两个好处。第一,它允许你修正错误。第二,它防止程序自动终止。大多数用户对于在程序终止运行和在无论何时错误发生都会打印堆栈轨迹感到很烦恼(至少可以这么说)。幸运的是,这很容易避免。为防止和处理一个运行时错误,只需要把你所要监控的代码放进一个try块就可以了。紧跟着try块的,包括一个说明你希望捕获的错误类型的catch子句。完成这个任务很简单,下面的程序包含一个处理因为被零除而产生的ArithmeticException 异常的try块和一个catch子句。
class Exc2 {
public static void main(String args[]) {
int d, a;
try { // monitor a block of code.
d = 0;
a = 42 / d;
System.out.println("This will not be printed.");
} catch (ArithmeticException e) { // catch divide-by-zero error
System.out.println("Division by zero.");
}
System.out.println("After catch statement.");
}
}
该程序输出如下:
Division by zero.
After catch statement.
注意在try块中的对println( )的调用是永远不会执行的。一旦异常被引发,程序控制由try块转到catch块。执行永远不会从catch块“返回”到try块。因此,“This will not be printed。”将不会被显示。一旦执行了catch语句,程序控制从整个try/catch机制的下面一行继续。一个try和它的catch语句形成了一个单元。catch子句的范围限制于try语句前面所定义的语句。一个catch语句不能捕获另一个try声明所引发的异常(除非是嵌套的try语句情况)。被try保护的语句声明必须在一个大括号之内(也就是说,它们必须在一个块中)。你不能单独使用try。
构造catch子句的目的是解决异常情况并且像错误没有发生一样继续运行。例如,下面的程序中,每一个for循环的反复得到两个随机整数。这两个整数分别被对方除,结果用来除12345。最后的结果存在a中。如果一个除法操作导致被零除错误,它将被捕获,a的值设为零,程序继续运行。
// Handle an exception and move on.
import java.util.Random;
class HandleError {
public static void main(String args[]) {
int a=0, b=0, c=0;
Random r = new Random();
for(int i=0; i<32000; i++) {
try {
b = r.nextInt();
c = r.nextInt();
a = 12345 / (b/c);
} catch (ArithmeticException e) {
System.out.println("Division by zero.");
a = 0; // set a to zero and continue
}
System.out.println("a: " + a);
}
}
}
10.4.1 显示一个异常的描述
Throwable重载toString( )方法(由Object定义),所以它返回一个包含异常描述的字符串。你可以通过在println( )中传给异常一个参数来显示该异常的描述。例如,前面程序的catch块可以被重写成
catch (ArithmeticException e) {
System.out.println("Exception: " + e);
a = 0; // set a to zero and continue
}
当这个版本代替原程序中的版本,程序在标准javaJDK解释器下运行,每一个被零除错误显示下面的消息:
Exception: java.lang.ArithmeticException: / by zero
尽管在上下文中没有特殊的值,显示一个异常描述的能力在其他情况下是很有价值的——特别是当你对异常进行实验和调试时。
10.5 使用多重catch 语句
某些情况,由单个代码段可能引起多个异常。处理这种情况,你可以定义两个或更多的catch子句,每个子句捕获一种类型的异常。当异常被引发时,每一个catch子句被依次检查,第一个匹配异常类型的子句执行。当一个catch语句执行以后,其他的子句被旁路,执行从try/catch块以后的代码开始继续。下面的例子设计了两种不同的异常类型:
// Demonstrate multiple catch statements.
class MultiCatch {
public static void main(String args[]) {
try {
int a = args.length;
System.out.println("a = " + a);
int b = 42 / a;
int c[] = { 1 };
c[42] = 99;
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index oob: " + e);
}
System.out.println("After try/catch blocks.");
}
}
该程序在没有命令行参数的起始条件下运行导致被零除异常,因为a为0。如果你提供一个命令行参数,它将幸免于难,把a设成大于零的数值。但是它将导致arrayIndexOutOf
BoundsException异常,因为整型数组c的长度为1,而程序试图给c[42]赋值。下面是运行在两种不同情况下程序的输出:
C:\>java MultiCatch
a = 0
Divide by 0: java.lang.ArithmeticException: / by zero
After try/catch blocks.
C:\>java MultiCatch TestArg
a = 1
Array index oob: java.lang.ArrayIndexOutOfBoundsException
After try/catch blocks.
当你用多catch语句时,记住异常子类必须在它们任何父类之前使用是很重要的。这是因为运用父类的catch语句将捕获该类型及其所有子类类型的异常。这样,如果子类在父类
后面,子类将永远不会到达。而且,Java中不能到达的代码是一个错误。例如,考虑下面的程序:
/* This program contains an error.
A subclass must come before its superclass in
a series of catch statements. If not,
unreachable code will be created and a
compile-time error will result.
*/
class SuperSubCatch {
public static void main(String args[]) {
try {
int a = 0;
int b = 42 / a;
} catch(Exception e) {
System.out.println("Generic Exception catch.");
}
/* This catch is never reached because
ArithmeticException is a subclass of Exception. */
catch(ArithmeticException e) { // ERROR - unreachable
System.out.println("This is never reached.");
}
}
}
如果你试着编译该程序,你会收到一个错误消息,该错误消息说明第二个catch语句不会到达,因为该异常已经被捕获。因为ArithmeticException 是Exception的子类,第一个catch语句将处理所有的面向Exception的错误,包括ArithmeticException。这意味着第二个catch语句永远不会执行。为修改程序,颠倒两个catch语句的次序。
10.6 嵌套try语句
Try语句可以被嵌套。也就是说,一个try语句可以在另一个try块内部。每次进入try语句,异常的前后关系都会被推入堆栈。如果一个内部的try语句不含特殊异常的catch处理程
序,堆栈将弹出,下一个try语句的catch处理程序将检查是否与之匹配。这个过程将继续直到一个catch语句匹配成功,或者是直到所有的嵌套try语句被检查耗尽。如果没有catch语句匹配,Java的运行时系统将处理这个异常。下面是运用嵌套try语句的一个例子:
// An example of nested try statements.
class NestTry {
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
如你所见,该程序在一个try块中嵌套了另一个try块。程序工作如下:当你在没有命令行参数的情况下执行该程序,外面的try块将产生一个被零除的异常。程序在有一个命令行
参数条件下执行,由嵌套的try块产生一个被零除的错误。因为内部的块不匹配这个异常,它将把异常传给外部的try块,在那里异常被处理。如果你在具有两个命令行参数的条件下执行该程序,由内部try块产生一个数组边界异常。下面的结果阐述了每一种情况:
C:\>java NestTry
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One
a = 1
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One Two
a = 2
Array index out-of-bounds: java.lang.ArrayIndexOutOfBoundsException当有方法调用时,try语句的嵌套可以很隐蔽的发生。例如,你可以把对方法的调用放在一个try块中。在该方法内部,有另一个try语句。这种情况下,方法内部的try仍然是嵌套在外部调用该方法的try块中的。下面是前面例子的修改,嵌套的try块移到了方法nesttry( )的内部:
/* Try statements can be implicitly nested via
calls to methods. */
class MethNestTry {
static void nesttry(int a) {
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
}
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
nesttry(a);
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
编辑 | 删除 | 权限设置 | 更多▼ 设置置顶
推荐日志
转到私密记事本
阿飞 发表于2009年04月04日 08:45 阅读(2) 评论(0)
分类: 个人日记 权限: 公开
本章介绍Java的异常处理机制。异常(exception)是在运行时代码序列中产生一种异常情况。换句话说,异常是一个运行时错误。在不支持异常处理的计算机语言中,错误必须被手工的检查和处理——典型的是通过错误代码的运用等等。这种方法既很笨拙也很麻烦。Java的异常处理避免了这些问题,而且在处理过程中,把运行时错误的管理带到了面向对象的世界。
10.1 异常处理基础
Java异常是一个描述在代码段中发生的异常(也就是出错)情况的对象。当异常情况发生,一个代表该异常的对象被创建并且在导致该错误的方法中被引发(throw)。该方法可以选择自己处理异常或传递该异常。两种情况下,该异常被捕获(caught)并处理。异常可能是由Java运行时系统产生,或者是由你的手工代码产生。被Java引发的异常与违反语言规范或超出Java执行环境限制的基本错误有关。手工编码产生的异常基本上用于报告方法调用程序的出错状况。Java异常处理通过5个关键字控制:try、catch、throw、throws和 finally。下面讲述它们如何工作的。程序声明了你想要的异常监控包含在一个try块中。如果在try块中发生异常,它被抛出。你的代码可以捕捉这个异常(用catch)并且用某种合理的方法处理该异常。系统产生的异常被Java运行时系统自动引发。手动引发一个异常,用关键字throw。任何被引发方法的异常都必须通过throws子句定义。任何在方法返回前绝对被执行的代码被放置在finally块中。
下面是一个异常处理块的通常形式:
try {
// block of code to monitor for errors
}
catch (ExceptionType1 exOb) {
// exception handler for ExceptionType1
}
catch (ExceptionType2 exOb) {
// exception handler for ExceptionType2
}
// ...
finally {
// block of code to be executed before try block ends
}
这里,ExceptionType 是发生异常的类型。下面将介绍怎样应用这个框架。
10.2 异 常 类 型
所有异常类型都是内置类Throwable的子类。因此,Throwable在异常类层次结构的顶层。紧接着Throwable下面的是两个把异常分成两个不同分支的子类。一个分支是Exception。该类用于用户程序可能捕捉的异常情况。它也是你可以用来创建你自己用户异常类型子类的类。在Exception分支中有一个重要子类RuntimeException。该类型的异常自动为你所编写的程序定义并且包括被零除和非法数组索引这样的错误。另一类分支由Error作为顶层,Error定义了在通常环境下不希望被程序捕获的异常。Error类型的异常用于Java运行时系统来显示与运行时系统本身有关的错误。堆栈溢出是这种错误的一例。本章将不讨论关于Error类型的异常处理,因为它们通常是灾难性的致命错误,不是你的程序可以控制的。
10.3 未被捕获的异常
在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的。下面的小程序包括一个故意导致被零除错误的表达式。
class Exc0 {
public static void main(String args[]) {
int d = 0;
int a = 42 / d;
}
}
当Java运行时系统检查到被零除的情况,它构造一个新的异常对象然后引发该异常。这导致Exc0的执行停止,因为一旦一个异常被引发,它必须被一个异常处理程序捕获并且被立即处理。该例中,我们没有提供任何我们自己的异常处理程序,所以异常被Java运行时系统的默认处理程序捕获。任何不是被你程序捕获的异常最终都会被该默认处理程序处理。默认处理程序显示一个描述异常的字符串,打印异常发生处的堆栈轨迹并且终止程序。下面是由标准javaJDK运行时解释器执行该程序所产生的输出:
java.lang.ArithmeticException: / by zero
at Exc0.main(Exc0.java:4)
注意,类名Exc0,方法名main,文件名Exc0.java和行数4是怎样被包括在一个简单的堆栈使用轨迹中的。还有,注意引发的异常类型是Exception的一个名为ArithmeticException
的子类,该子类更明确的描述了何种类型的错误方法。本章后面部分将讨论,Java提供多个内置的与可能产生的不同种类运行时错误相匹配的异常类型。堆栈轨迹将显示导致错误产生的方法调用序列。例如,下面是前面程序的另一个版本,它介绍了相同的错误,但是错误是在main( )方法之外的另一个方法中产生的:
class Exc1 {
static void subroutine() {
int d = 0;
int a = 10 / d;
}
public static void main(String args[]) {
Exc1.subroutine();
}
}
默认异常处理器的堆栈轨迹结果表明了整个调用栈是怎样显示的:
java.lang.ArithmeticException: / by zero
at Exc1.subroutine(Exc1.java:4)
at Exc1.main(Exc1.java:7)
如你所见,栈底是main的第7行,该行调用了subroutine( )方法。该方法在第4行导致了异常。调用堆栈对于调试来说是很重要的,因为它查明了导致错误的精确的步骤。
10.4 使用try和catch
尽管由Java运行时系统提供的默认异常处理程序对于调试是很有用的,但通常你希望自己处理异常。这样做有两个好处。第一,它允许你修正错误。第二,它防止程序自动终止。大多数用户对于在程序终止运行和在无论何时错误发生都会打印堆栈轨迹感到很烦恼(至少可以这么说)。幸运的是,这很容易避免。为防止和处理一个运行时错误,只需要把你所要监控的代码放进一个try块就可以了。紧跟着try块的,包括一个说明你希望捕获的错误类型的catch子句。完成这个任务很简单,下面的程序包含一个处理因为被零除而产生的ArithmeticException 异常的try块和一个catch子句。
class Exc2 {
public static void main(String args[]) {
int d, a;
try { // monitor a block of code.
d = 0;
a = 42 / d;
System.out.println("This will not be printed.");
} catch (ArithmeticException e) { // catch divide-by-zero error
System.out.println("Division by zero.");
}
System.out.println("After catch statement.");
}
}
该程序输出如下:
Division by zero.
After catch statement.
注意在try块中的对println( )的调用是永远不会执行的。一旦异常被引发,程序控制由try块转到catch块。执行永远不会从catch块“返回”到try块。因此,“This will not be printed。”将不会被显示。一旦执行了catch语句,程序控制从整个try/catch机制的下面一行继续。一个try和它的catch语句形成了一个单元。catch子句的范围限制于try语句前面所定义的语句。一个catch语句不能捕获另一个try声明所引发的异常(除非是嵌套的try语句情况)。被try保护的语句声明必须在一个大括号之内(也就是说,它们必须在一个块中)。你不能单独使用try。
构造catch子句的目的是解决异常情况并且像错误没有发生一样继续运行。例如,下面的程序中,每一个for循环的反复得到两个随机整数。这两个整数分别被对方除,结果用来除12345。最后的结果存在a中。如果一个除法操作导致被零除错误,它将被捕获,a的值设为零,程序继续运行。
// Handle an exception and move on.
import java.util.Random;
class HandleError {
public static void main(String args[]) {
int a=0, b=0, c=0;
Random r = new Random();
for(int i=0; i<32000; i++) {
try {
b = r.nextInt();
c = r.nextInt();
a = 12345 / (b/c);
} catch (ArithmeticException e) {
System.out.println("Division by zero.");
a = 0; // set a to zero and continue
}
System.out.println("a: " + a);
}
}
}
10.4.1 显示一个异常的描述
Throwable重载toString( )方法(由Object定义),所以它返回一个包含异常描述的字符串。你可以通过在println( )中传给异常一个参数来显示该异常的描述。例如,前面程序的catch块可以被重写成
catch (ArithmeticException e) {
System.out.println("Exception: " + e);
a = 0; // set a to zero and continue
}
当这个版本代替原程序中的版本,程序在标准javaJDK解释器下运行,每一个被零除错误显示下面的消息:
Exception: java.lang.ArithmeticException: / by zero
尽管在上下文中没有特殊的值,显示一个异常描述的能力在其他情况下是很有价值的——特别是当你对异常进行实验和调试时。
10.5 使用多重catch 语句
某些情况,由单个代码段可能引起多个异常。处理这种情况,你可以定义两个或更多的catch子句,每个子句捕获一种类型的异常。当异常被引发时,每一个catch子句被依次检查,第一个匹配异常类型的子句执行。当一个catch语句执行以后,其他的子句被旁路,执行从try/catch块以后的代码开始继续。下面的例子设计了两种不同的异常类型:
// Demonstrate multiple catch statements.
class MultiCatch {
public static void main(String args[]) {
try {
int a = args.length;
System.out.println("a = " + a);
int b = 42 / a;
int c[] = { 1 };
c[42] = 99;
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index oob: " + e);
}
System.out.println("After try/catch blocks.");
}
}
该程序在没有命令行参数的起始条件下运行导致被零除异常,因为a为0。如果你提供一个命令行参数,它将幸免于难,把a设成大于零的数值。但是它将导致arrayIndexOutOf
BoundsException异常,因为整型数组c的长度为1,而程序试图给c[42]赋值。下面是运行在两种不同情况下程序的输出:
C:\>java MultiCatch
a = 0
Divide by 0: java.lang.ArithmeticException: / by zero
After try/catch blocks.
C:\>java MultiCatch TestArg
a = 1
Array index oob: java.lang.ArrayIndexOutOfBoundsException
After try/catch blocks.
当你用多catch语句时,记住异常子类必须在它们任何父类之前使用是很重要的。这是因为运用父类的catch语句将捕获该类型及其所有子类类型的异常。这样,如果子类在父类
后面,子类将永远不会到达。而且,Java中不能到达的代码是一个错误。例如,考虑下面的程序:
/* This program contains an error.
A subclass must come before its superclass in
a series of catch statements. If not,
unreachable code will be created and a
compile-time error will result.
*/
class SuperSubCatch {
public static void main(String args[]) {
try {
int a = 0;
int b = 42 / a;
} catch(Exception e) {
System.out.println("Generic Exception catch.");
}
/* This catch is never reached because
ArithmeticException is a subclass of Exception. */
catch(ArithmeticException e) { // ERROR - unreachable
System.out.println("This is never reached.");
}
}
}
如果你试着编译该程序,你会收到一个错误消息,该错误消息说明第二个catch语句不会到达,因为该异常已经被捕获。因为ArithmeticException 是Exception的子类,第一个catch语句将处理所有的面向Exception的错误,包括ArithmeticException。这意味着第二个catch语句永远不会执行。为修改程序,颠倒两个catch语句的次序。
10.6 嵌套try语句
Try语句可以被嵌套。也就是说,一个try语句可以在另一个try块内部。每次进入try语句,异常的前后关系都会被推入堆栈。如果一个内部的try语句不含特殊异常的catch处理程
序,堆栈将弹出,下一个try语句的catch处理程序将检查是否与之匹配。这个过程将继续直到一个catch语句匹配成功,或者是直到所有的嵌套try语句被检查耗尽。如果没有catch语句匹配,Java的运行时系统将处理这个异常。下面是运用嵌套try语句的一个例子:
// An example of nested try statements.
class NestTry {
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
如你所见,该程序在一个try块中嵌套了另一个try块。程序工作如下:当你在没有命令行参数的情况下执行该程序,外面的try块将产生一个被零除的异常。程序在有一个命令行
参数条件下执行,由嵌套的try块产生一个被零除的错误。因为内部的块不匹配这个异常,它将把异常传给外部的try块,在那里异常被处理。如果你在具有两个命令行参数的条件下执行该程序,由内部try块产生一个数组边界异常。下面的结果阐述了每一种情况:
C:\>java NestTry
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One
a = 1
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One Two
a = 2
Array index out-of-bounds: java.lang.ArrayIndexOutOfBoundsException当有方法调用时,try语句的嵌套可以很隐蔽的发生。例如,你可以把对方法的调用放在一个try块中。在该方法内部,有另一个try语句。这种情况下,方法内部的try仍然是嵌套在外部调用该方法的try块中的。下面是前面例子的修改,嵌套的try块移到了方法nesttry( )的内部:
/* Try statements can be implicitly nested via
calls to methods. */
class MethNestTry {
static void nesttry(int a) {
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
}
public static void main(String args[]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
nesttry(a);
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
发表评论
-
我的观察者模式
2010-07-07 16:59 1007package pattern; import java.u ... -
面试题记
2009-10-13 10:50 1137今天在学校里进行了第二次面试,这次面试官什么都不讲,只讲编程水 ... -
参数传递2
2009-09-29 10:20 928java的设计者对底层的java实现代码做了太多封装,和C语言 ... -
关于程序语言中的参数传递
2009-09-19 10:25 953关于程序语言中的值传递问题很是让人迷惑,在此,更具自己的理 ... -
暑期学习总结
2009-08-24 09:15 1163时间:2009年8月18号;下午2:45. ... -
Servlet方面的理解
2009-06-26 23:02 994牛顿有一句话:站在巨人的肩上,我们可以看的更远!这里我修改一下 ... -
jaava的八大优点
2009-06-23 00:27 1173我们为什么要学习java呢 ... -
异常理解
2009-06-12 22:00 973今天终于把困扰自己一段时间的java异常彻底解决了,心 ... -
有关字符编码
2009-06-06 09:33 821UNICODE,GBK,UTF-8区别(转)2008-11-2 ... -
一个连接池的实现,很不错!
2009-05-04 12:13 1154下面是一个连接池的简单实现: 虽然很简单,但是和网上流行的连接 ...
相关推荐
qt 一个基于Qt Creator(qt,C++)实现中国象棋人机对战.
热带雨林自驾游自然奇观探索
冰川湖自驾游冰雪交融景象
C51 单片机数码管使用 Keil项目C语言源码
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
前端分析-2023071100789s12
Laz_制作了一些窗体和对话框样式.7z
1、文件内容:ocaml-docs-4.05.0-6.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ocaml-docs-4.05.0-6.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
学习笔记-沁恒第六讲-米醋
工业机器人技术讲解【36页】
内容概要:本文档详细介绍了在 CentOS 7 上利用 Docker 容器化环境来部署和配置 Elasticsearch 数据库的过程。首先概述了 Elasticsearch 的特点及其主要应用场景如全文检索、日志和数据分析等,并强调了其分布式架构带来的高性能与可扩展性。之后针对具体的安装流程进行了讲解,涉及创建所需的工作目录,准备docker-compose.yml文件以及通过docker-compose工具自动化完成镜像下载和服务启动的一系列命令;同时对可能出现的问题提供了应对策略并附带解决了分词功能出现的问题。 适合人群:从事IT运维工作的技术人员或对NoSQL数据库感兴趣的开发者。 使用场景及目标:该教程旨在帮助读者掌握如何在一个Linux系统中使用现代化的应用交付方式搭建企业级搜索引擎解决方案,特别适用于希望深入了解Elastic Stack生态体系的个人研究与团队项目实践中。 阅读建议:建议按照文中给出的具体步骤进行实验验证,尤其是要注意调整相关参数配置适配自身环境。对于初次接触此话题的朋友来说,应该提前熟悉一下Linux操作系统的基础命令行知识和Docker的相关基础知识
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
网络小说的类型创新、情节设计与角色塑造
毕业设计_基于springboot+vue开发的学生考勤管理系统【源码+sql+可运行】【50311】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - 业务管理:班级信息、学生信息、课程信息、考勤记录、假期信息、公告信息 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
内容概要:本文介绍了使用 Matlab 实现基于 BO(贝叶斯优化)的 Transformer 结合 GRU 门控循环单元时间序列预测的具体项目案例。文章首先介绍了时间序列预测的重要性及其现有方法存在的限制,随后深入阐述了该项目的目标、挑战与特色。重点描述了项目中采用的技术手段——结合 Transformer 和 GRU 模型的优点,通过贝叶斯优化进行超参数调整。文中给出了模型的具体实现步骤、代码示例以及完整的项目流程。同时强调了数据预处理、特征提取、窗口化分割、超参数搜索等关键技术点,并讨论了系统的设计部署细节、可视化界面制作等内容。 适合人群:具有一定机器学习基础,尤其是熟悉时间序列预测与深度学习的科研工作者或从业者。 使用场景及目标:适用于金融、医疗、能源等多个行业的高精度时间序列预测。该模型可通过捕捉长时间跨度下的复杂模式,提供更为精准的趋势预判,辅助相关机构作出合理的前瞻规划。 其他说明:此项目还涵盖了从数据采集到模型发布的全流程讲解,以及GUI图形用户界面的设计实现,有助于用户友好性提升和技术应用落地。此外,文档包含了详尽的操作指南和丰富的附录资料,包括完整的程序清单、性能评价指标等,便于读者动手实践。
漫画与青少年教育关系
励志图书的成功案例分享、人生智慧提炼与自我提升策略
人工智能在食品安全与检测中的应用