Java提供了两类主要的异常:runtime exception和checked exception。所有的checked exception是从java.lang.Exception类衍生出来的,而runtime exception则是从java.lang.RuntimeException或java.lang.Error类衍生出来的。
它们的不同之处表现在两方面:机制上和逻辑上。
一、机制上
它们在机制上的不同表现在两点:1.如何定义方法;2. 如何处理抛出的异常。请看下面CheckedException的定义:
public class CheckedException extends Exception
{
public CheckedException() {}
public CheckedException( String message )
{
super( message );
}
}
以及一个使用exception的例子:
public class ExceptionalClass
{
public void method1()
throws CheckedException
{
// ... throw new CheckedException( “...出错了“ );
}
public void method2( String arg )
{
if( arg == null )
{
throw new NullPointerException( “method2的参数arg是null!” );
}
}
public void method3() throws CheckedException
{
method1();
}
}
你可能已经注意到了,两个方法method1()和method2()都会抛出exception,可是只有method1()做了声明。另外,method3()本身并不会抛出exception,可是它却声明会抛出CheckedException。在向你解释之前,让我们先来看看这个类的main()方法:
public static void main( String[] args )
{
ExceptionalClass example = new ExceptionalClass();
try
{
example.method1();
example.method3();
}
catch( CheckedException ex ) { } example.method2( null );
}
在main()方法中,如果要调用method1(),你必须把这个调用放在try/catch程序块当中,因为它会抛出Checked exception。
相比之下,当你调用method2()时,则不需要把它放在try/catch程序块当中,因为它会抛出的exception不是checked exception,而是runtime exception。会抛出runtime exception的方法在定义时不必声明它会抛出exception。
现在,让我们再来看看method3()。它调用了 method1()却没有把这个调用放在try/catch程序块当中。它是通过声明它会抛出method1()会抛出的exception来避免这样做的。它没有捕获这个exception,而是把它传递下去。实际上main()方法也可以这样做,通过声明它会抛出Checked exception来避免使用try/catch程序块(当然我们反对这种做法)。
小结一下:
* Runtime exceptions:
在定义方法时不需要声明会抛出runtime exception;
在调用这个方法时不需要捕获这个runtime exception;
runtime exception是从java.lang.RuntimeException或java.lang.Error类衍生出来的。
* Checked exceptions:
定义方法时必须声明所有可能会抛出的checked exception;
在调用这个方法时,必须捕获它的checked exception,不然就得把它的exception传递下去;
checked exception是从java.lang.Exception类衍生出来的。
二、逻辑上
从逻辑的角度来说,checked exceptions和runtime exception是有不同的使用目的的。checked exception用来指示一种调用方能够直接处理的异常情况。而runtime exception则用来指示一种调用方本身无法处理或恢复的程序错误。
checked exception迫使你捕获它并处理这种异常情况。以java.net.URL类的构建器(constructor)为例,它的每一个构建器都会抛出 MalformedURLException。MalformedURLException就是一种checked exception。设想一下,你有一个简单的程序,用来提示用户输入一个URL,然后通过这个URL去下载一个网页。如果用户输入的URL有错误,构建器就会抛出一个exception。既然这个exception是checked exception,你的程序就可以捕获它并正确处理:比如说提示用户重新输入。
再看下面这个例子:
public void method()
{
int [] numbers = { 1, 2, 3 };
int sum = numbers[0] numbers[3];
}
在运行方法method()时会遇到ArrayIndexOutOfBoundsException(因为数组numbers的成员是从0到2)。对于这个异常,调用方无法处理/纠正。这个方法method()和上面的method2()一样,都是runtime exception的情形。上面我已经提到,runtime exception用来指示一种调用方本身无法处理/恢复的程序错误。而程序错误通常是无法在运行过程中处理的,必须改正程序代码。
总而言之,在程序的运行过程中一个checked exception被抛出的时候,只有能够适当处理这个异常的调用方才应该用try/catch来捕获它。而对于runtime exception,则不应当在程序中捕获它。如果你要捕获它的话,你就会冒这样一个风险:程序代码的错误(bug)被掩盖在运行当中无法被察觉。因为在程序测试过程中,系统打印出来的调用堆栈路径(StackTrace)往往使你更快找到并修改代码中的错误。有些程序员建议捕获runtime exception并纪录在log中,我反对这样做。这样做的坏处是你必须通过浏览log来找出问题,而用来测试程序的测试系统(比如Unit Test)却无法直接捕获问题并报告出来。
在程序中捕获runtime exception还会带来更多的问题:要捕获哪些runtime exception?什么时候捕获?runtime exception是不需要声明的,你怎样知道有没有runtime exception要捕获?你想看到在程序中每一次调用方法时,都使用try/catch程序块吗?
转载自:
http://www.enet.com.cn/article/2005/1027/A20051027466203_2.shtml
分享到:
相关推荐
浅析Java语言中线程的生命周期及实现方式 Java语言中的线程(Thread)是指在同一个进程中可以并发执行的多个控制流程。线程是Java语言中定义的非常重要的基本概念和技术标准。随着整个社会信息化的发展,传统服务器...
Java 与 JavaScript 脚本是两种不同的编程语言,它们在 Web 开发中扮演着重要的角色。虽然它们都可以嵌入到 HTML 页面中,但是它们的表示方式、执行过程和应用场景都是不一样的。 首先,我们来看看 Java 脚本。...
在面向对象编程领域,C++和Java是最典型且广泛使用的两种语言。了解它们之间的差异对于软件开发人员至关重要。 面向对象(Object-Oriented, OO)是当今计算机科学的核心,90年代以来已成为软件开发的主流范式。它的...
在这一点上,两种语言之间的差异并不显著,但Java中的多态性使用更为广泛,尤其是在利用接口实现设计模式方面。 综上所述,Java与C++在许多方面都有着明显的区别。这些区别不仅体现在语言的语法结构上,更体现在...
在Java编程语言中,抽象类和接口是两种面向对象编程(OOP)机制,用以实现抽象概念的不同方式。理解这两者之间的区别对于掌握Java的面向对象特性至关重要,尤其在设计软件架构时。以下将详细分析Java中抽象类和接口...
在Java编程语言中,抽象类和接口是两种重要的面向对象设计概念,它们都用于实现多态性,但各自具有不同的特点和应用场景。本篇文章将详细分析这两种机制的区别,以帮助开发者更好地理解和运用。 首先,抽象类是类的...
### Java中堆内存与栈内存分配浅析 #### 一、引言 在Java编程语言中,内存管理是一项至关重要的技术。程序运行时所使用的内存主要分为两类:堆内存(Heap Memory)和栈内存(Stack Memory)。理解这两种内存类型的...
Java NIO是Java语言中用于高性能I/O操作的API,理解IO模型是学习Java NIO的基础。本文将从同步和异步的概念开始,然后介绍阻塞和非阻塞的区别,接着介绍阻塞IO和非阻塞IO的区别,最后介绍五种IO模型和两种高性能IO...
在Java编程语言中,创建和管理多线程有两种主要的方式:继承`Thread`类和实现`Runnable`接口。这两种方式都是为了实现并发执行任务,但它们之间存在一些关键的区别。 首先,当我们创建一个新的线程时,实际上是为了...
在Java编程中,与C++或C等语言相比,开发者无需手动管理内存,因为Java引入了一种自动的内存管理机制——垃圾回收(Garbage Collection,简称GC)。垃圾回收器负责监测并回收不再使用的对象所占用的内存空间,以防止...
在Java编程语言中,String和StringBuffer类都用于处理字符串,但它们在处理字符串拼接时有着显著的区别。本文将详细解析这两个类在拼接字符串时的行为差异。 首先,我们来了解一下String类。String对象在Java中是不...
Java中的多态可以通过覆盖和重载两种方式实现。 #### Java中的引用详解 在Java中,对象是通过引用(Reference)来访问的。引用是指向对象的一个指针,而不是对象本身。理解引用的概念对于深入掌握Java非常重要。 ...
Java集合框架是Java编程语言中处理数据结构的一个强大工具包,它提供了一系列灵活高效的接口和实现来帮助开发者管理数据。本篇文章将重点介绍Java中常用的集合类——`Collection`和`Map`及其相关子类,并探讨它们...
在Java编程语言中,继承和组合是两种主要的面向对象设计原则,它们分别代表了类之间的不同关系。本文将深入探讨这两个概念以及它们在实际编程中的应用和选择。 首先,让我们了解一下继承。继承是Java中一种强大的...
C语言、Java和Python这三种编程语言虽然在数组合并的方法上有所差异,但它们都为数组合并操作提供了相对便捷的方式。以下是这些语言在数组合并方面的详细知识点: C语言数组合并: 在C语言中,由于语言的低级特性,...
在Java编程语言中,Comparable和Comparator接口都用于比较对象,但它们之间存在一些关键区别,这对于理解和优化代码的可扩展性至关重要。 首先,Comparable接口是一个排序接口,它定义了一个单一的方法`compareTo(T...
例如,在上述示例的for循环中,我们看到两种不同的操作方式: 1. **方法入参**:在方法中通过对象引用参数修改对象属性,如: ```java void updateUser(User user) { user.setName("newName"); } ``` 这会...
Java编程语言中,变量是程序的基本构建块,用于存储数据。根据它们的作用域和生命周期,变量分为两类:成员变量和局部变量。理解这两者的区别对于编写清晰、有效的Java代码至关重要。 成员变量,也称为实例变量,是...
BBS(Bulletin Board System,电子公告牌)和 Blog 是两种不同的网络应用,虽然它们都提供了信息共享和交流的平台,但它们在许多方面存在着明显的区别。 1.适用范围不同 BBS 是一个开放的、自由的空间,面向的是一...
Java 和 C 语言是两种广泛使用的编程语言,它们在设计理念、特性和应用上存在显著的差异。虽然两者都属于高级编程语言,但它们的核心特点和使用场景有所不同。 首先,Java 是一种面向对象的语言,它的设计目标是...