package testexcrpltiom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
import cn.zdsoft.test.Test2;
import myutils.MyUtils;
/**
* 测试异常
* @author Administrator
*
*/
public class TestException
{ Test test;
public static void main(String[] args)
{ //空指针异常
//Test.getName();
//算术异常
//System.out.println(1/0);
//下标越界异常
//int [] a={1,2,3};
//System.out.println(a[3]);
//类型转换异常
//Object obj=new TestException();
//String str=(String)obj;
String str="2013-11-22";
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
try
{ //放入可能有异常的代码 可以多条
sdf.parse(str);
}// eatch 可以有多个来定义不同类型的 异常
catch (ParseException e)
{
//对捕获到的异常进行什么样的处理
e.printStackTrace();
}//可以加可以不加 但是只能跟在try catch 后面 且只能有一个 作用不管有没有异常都要执行里面的代码
finally
{
}
}
}
package testexcrpltiom;
//自定义一个异常类 需要继承Exception 或者runtimeException
public class CousonException extends Exception
{
//无参构造器
public CousonException()
{
//异常的提示语句
this("余额不足");
}
//有参构造器
public CousonException(String str)
{
//调用了父类的有参构造器将提示传上去
super(str);
}
}
*创建一个运行时的异常 需要继承RuntimeException
*/
public class TestRuntimeException extends RuntimeException
{
//定义一个无参构造器用来调用有参构造器来传递 提示
public TestRuntimeException()
{
this("你的钱不够啊");
}
public TestRuntimeException(String str)
{
//将提示内容传递给父类的有参构造器
super(str);
}
}
package testexcrpltiom;
/**
*
* 将异常添加到需要抛出异常的地方
*
*/
public class Mai
{
//在需要抛出异常的方法中要先声明要抛出的异常类型
public void mai(double m)
throws
CousonException
{
if(m-90<0)
{
//在实际要抛出异常的地方在throw 进行异常的抛出
throw new CousonException();
}
}
}
Java异常学习心得
Java 异常学习心得
本文重在 Java 中异常机制的一些概念。写本文的目的在于方便我很长时间后若是忘了这些东西可以通过这片文章迅速回忆起来。
1. 异常机制
1.1
异常机制是指当程序出现错误后,程序如何处理。具体来说,异常机制提供了程序退出的安全通道。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。
1.2
传统的处理异常的办法是,函数返回一个特殊的结果来表示出现异常(通常这个特殊结果是大家约定俗称的),调用该函数的程序负责检查并分析函数返回的结果。这样做有如下的弊端:例如函数返回 -1 代表出现异常,但是如果函数确实要返回 -1 这个正确的值时就会出现混淆;可读性降低,将程序代码与处理异常的代码混爹在一起;由调用函数的程序来分析错误,这就要求客户程序员对库函数有很深的了解。
1.3 异常处理的流程
1.3.1 遇到错误,方法立即结束,并不返回一个值;同时,抛出一个异常对象
1.3.2 调用该方法的程序也不会继续执行下去,而是搜索一个可以处理该异常的异常处理器,并执行其中的代码
2 异常的分类
2.1 异常的分类
2.1.1
异常的继承结构:基类为 Throwable , Error 和 Exception 继承 Throwable , RuntimeException 和 IOException 等继承 Exception ,具体的 RuntimeException 继承 RuntimeException 。
2.1.2
Error 和 RuntimeException 及其子类成为未检查异常( unchecked ),其它异常成为已检查异常( checked )。
2.2 每个类型的异常的特点
2.2.1 Error 体系
Error 类体系描述了 Java 运行系统中的内部错误以及资源耗尽的情形。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以,在进行程序设计时,应该更关注 Exception 体系。
2.2.2 Exception 体系
Exception 体系包括 RuntimeException 体系和其他非 RuntimeException 的体系
2.2.2.1 RuntimeException
RuntimeException 体系包括错误的类型转换、数组越界访问和试图访问空指针等等。处理 RuntimeException 的原则是:如果出现 RuntimeException ,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
2.2.2.2 其他( IOException 等等)
这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
2.3 与 C++ 异常分类的不同
2.3.1
其实, Java 中 RuntimeException 这个类名起的并不恰当,因为任何异常都是运行时出现的。(在编译时出现的错误并不是异常,换句话说,异常就是为了解决程序运行时出现的的错误)。
2.3.2
C++ 中 logic_error 与 Java 中的 RuntimeException 是等价的,而 runtime_error 与 Java 中非 RuntimeException 类型的异常是等价的。
3 异常的使用方法
3.1 声明方法抛出异常
3.1.1 语法: throws (略)
3.1.2 为什么要声明方法抛出异常?
方法是否抛出异常与方法返回值的类型一样重要。假设方法抛出异常确没有声明该方法将抛出异常,那么客户程序员可以调用这个方法而且不用编写处理异常的代码。那么,一旦出现异常,那么这个异常就没有合适的异常控制器来解决。
3.1.3 为什么抛出的异常一定是已检查异常?
RuntimeException 与 Error 可以在任何代码中产生,它们不需要由程序员显示的抛出,一旦出现错误,那么相应的异常会被自动抛出。而已检查异常是由程序员抛出的,这分为两种情况:客户程序员调用会抛出异常的库函数(库函数的异常由库程序员抛出);客户程序员自己使用 throw 语句抛出异常。遇到 Error ,程序员一般是无能为力的;遇到 RuntimeException ,那么一定是程序存在逻辑错误,要对程序进行修改(相当于调试的一种方法);只有已检查异常才是程序员所关心的,程序应该且仅应该抛出或处理已检查异常。
3.1.4
注意:覆盖父类某方法的子类方法不能抛出比父类方法更多的异常,所以,有时设计父类的方法时会声明抛出异常,但实际的实现方法的代码却并不抛出异常,这样做的目的就是为了方便子类方法覆盖父类方法时可以抛出异常。
3.2 如何抛出异常
3.2.1 语法: throw (略)
3.2.2 抛出什么异常?
对于一个异常对象,真正有用的信息时异常的对象类型,而异常对象本身毫无意义。比如一个异常对象的类型是 ClassCastException ,那么这个类名就是唯一有用的信息。所以,在选择抛出什么异常时,最关键的就是选择异常的类名能够明确说明异常情况的类。
3.2.3
异常对象通常有两种构造函数:一种是无参数的构造函数;另一种是带一个字符串的构造函数,这个字符串将作为这个异常对象除了类型名以外的额外说明。
3.2.4
创建自己的异常:当 Java 内置的异常都不能明确的说明异常情况的时候,需要创建自己的异常。需要注意的是,唯一有用的就是类型名这个信息,所以不要在异常类的设计上花费精力。
3.3 捕获异常
如果一个异常没有被处理,那么,对于一个非图形界面的程序而言,该程序会被中止并输出异常信息;对于一个图形界面程序,也会输出异常的信息,但是程序并不中止,而是返回用 Ы 缑娲 硌 分小 ?BR> 3.3.1 语法: try 、 catch 和 finally (略)
控制器模块必须紧接在 try 块后面。若掷出一个异常,异常控制机制会搜寻参数与异常类型相符的第一个控制器随后它会进入那个 catch
从句,并认为异常已得到控制。一旦 catch 从句结束对控制器的搜索也会停止。
3.3.1.1 捕获多个异常(注意语法与捕获的顺序)(略)
3.3.1.2 finally 的用法与异常处理流程(略)
3.3.2 异常处理做什么?
对于 Java 来说,由于有了垃圾收集,所以异常处理并不需要回收内存。但是依然有一些资源需要程序员来收集,比如文件、网络连接和图片等资源。
3.3.3 应该声明方法抛出异常还是在方法中捕获异常?
原则:捕捉并处理哪些知道如何处理的异常,而传递哪些不知道如何处理的异常
3.3.4 再次抛出异常
3.3.4.1 为什么要再次抛出异常?
在本级中,只能处理一部分内容,有些处理需要在更高一级的环境中完成,所以应该再次抛出异常。这样可以使每级的异常处理器处理它能够处理的异常。
3.3.4.2 异常处理流程
对应与同一 try 块的 catch 块将被忽略,抛出的异常将进入更高的一级。
4 关于异常的其他问题
4.1 过度使用异常
首先,使用异常很方便,所以程序员一般不再愿意编写处理错误的代码,而仅仅是简简单单的抛出一个异常。这样做是不对的,对于完全已知的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。另外,异常机制的效率很差。
4.2 将异常与普通错误区分开
对于普通的完全一致的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。只有外部的不能确定和预知的运行时错误才需要使用异常。
4.3 异常对象中包含的信息
一般情况下,异常对象唯一有用的信息就是类型信息。但使用异常带字符串的构造函数时,这个字符串还可以作为额外的信息。调用异常对象的 getMessage() 、 toString() 或者 printStackTrace() 方法可以分别得到异常对象的额外信息、类名和调用堆栈的信息。并且后一种包含的信息是前一种的超集。
用异常来处理错误
我们总是试图避免在软件程序中错误的发生,但是它的存在却是不幸的实事。无论怎样,如果你能适当的处理错误,将会极大的改善程序的可读性、可靠性以及可维护性。 Java 编程语言使用异常来处理错误。这章主要讲述在什么时候和怎样使用异常来处理错误。
什么是异常?
Java 编程语言使用异常机制为程序提供了错误处理的能力。一个异常是在程序执行期间发生的一个事件,它使用正常的指令流中断。
捕获或指定需求
这段讲述捕获和处理异常。在讨论中包括: try,catch 和 finally 程序块,还有异常链和日志。
怎样抛出异常
这段讲述异常抛出语句和 Throwable 类以及它的子类。
有关未检查的异常争论
因为 Java 编程语言不要求捕获或指定运行时异常或错误的方法,所以程序员会被诱导来编写只抛出运行时异常代码,在这段中我们会解释为什么不应该被诱导。
异常的好处
在这段中,你将会学到更多的使用异常来管理错误优于传统的错误管理技术方面的知识。
什么是异常?
异常( exception )应该是异常事件( exceptional event )的缩写。
异常定义:异常是一个在程序执行期间发生的事件,它中断正在执行的程序的正常的指令流。
当在一个方法中发生错误的时候,这个方法创建一个对象,并且把它传递给运行时系统。这个对象被叫做异常对象,它包含了有关错误的信息,这些信息包括错误的类型和在程序发生错误时的状态。创建一个错误对象并把它传递给运行时系统被叫做抛出异常。
一个方法抛出异常后,运行时系统就会试着查找一些方法来处理它。这些处理异常的可能的方法的集合是被整理在一起的方法列表,这些方法能够被发生错误的方法调用。这个方法列表被叫做堆栈调用( call stack ) , 调用方式如下图所示
运行时系统搜寻包含能够处理异常的代码块的方法所请求的堆栈。这个代码块叫做异常处理器,搜寻首先从发生的方法开始,然后依次按着调用方法的倒序检索调用堆栈。当找到一个相应的处理器时,运行时系统就把异常传递给这个处理器。一个异常处理器要适当地考滤抛出的异常对象的类型和异常处理器所处理的异常的类型是否匹配。异常被捕获以后,异常处理器关闭。如果运行时系统搜寻了这个方法的所有的调用堆栈,而没有找到相应的异常处理器,如下图所示,运行进系统将终止执行。
使用异常来管理错误比传统的错误管理技术有一些优势,你可以“异常的优势”一节学到更多的知识
异常管理的优势
你已经读了有关什么是异常以及怎样使用它们的内容,现在是学习在你的程序中使用异常的好处的时候了。
优势 1 :把规则代码与错误处理代码分离
异常处理规定把错误发生时所要的细节工作与程序的主逻辑代码分离。在传统程序中,错误的发现、报告以及处理经常使得代码混乱。例如,思考下面的伪代码,这是一个把整个文件读入内存的方法。
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
第一眼看上去,这个函数似乎很简单,但是它却忽略了所发生下面这些错误的可能。
<!-- [if !supportLists]-->1、 <!-- [endif]-->如果不能打开文件,会发生什么?
<!-- [if !supportLists]-->2、 <!-- [endif]-->如果不能判定文件的大小,会发生什么?
<!-- [if !supportLists]-->3、 <!-- [endif]-->如果没有足够的内存,会发生什么?
<!-- [if !supportLists]-->4、 <!-- [endif]-->如果读取失败,会发生什么?
<!-- [if !supportLists]-->5、 <!-- [endif]-->如果文件不能关闭。会发生什么?
要处理这些信息, readFile 函数必须用更多的代码来做错误发现、报告和处理工作。这个函数看上去可能象这样:
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
有如此多的错误发现、报告和返回,使得初的 7 行代码被埋没在混乱的错误代码之中。更严重的是,代码的逻辑流已经没有了,这样使得它很难说明代码是否正在做着正确的事情:如果函数在分配内存过程失败,文件真得的被关闭了吗?甚至更难保证在三个月之后,你编写的这段代码继续做正确的事情。
异常处理使你能够编写代码的主工作流并且在别的地方来处理异常信息。如果 readFile 函数使用异常处理来代替传统的错误管理技术,它应该像如下所示的代码这样:
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
注意:异常处理不会节省错误的发现、报告、处理的工作量,但是它们能够帮助你更有效的组织代码。
优势 2 :向调用堆栈上层传递错误
异常处理的第二个优势是向方法的调用堆栈上层传递错误报告的能力。假如 readFile 方法是主程序调用的一系列嵌套方法中的第四个方法:方法 1 调用方法 2 ,方法 2 调用方法 3 ,方法 3 调用 readFile ,代码结构如下所示:
method1 {
call method2;
}
method2 {
call method3;
}
method3 {
call readFile;
}
还假如 method1 是唯一的能够处理 readFile 方法中所可能发生的错误的方法,那么传统的错误处理技术会强制 method2 和 method3 来传递通过 readFile 调用堆栈所返回的错误代码,直到错误代码传递到 method1 -因为只有 method1 能够处理这些错误,其代码结构如下所示:
method1 {
errorCodeType error;
error = call method2;
if (error)
doErrorProcessing;
else
proceed;
}
errorCodeType method2 {
errorCodeType error;
error = call method3;
if (error)
return error;
else
proceed;
}
errorCodeType method3 {
errorCodeType error;
error = call readFile;
if (error)
return error;
else
proceed;
}
回忆一下, Java 运行时环境搜寻调用堆栈来查找任意的处理特殊的异常的方法。一个方法能够抛出它内部的任何异常,所以允许一个上层调用堆栈的方法来捕获它。因此只有处理相关错误的方法来处理发现的错误,代码结构如下所示:
method1 {
try {
call method2;
} catch (exception e) {
doErrorProcessing;
}
}
method2 throws exception {
call method3;
}
method3 throws exception {
call readFile;
}
无论怎样,就像伪代码所展示的那样,躲避异常需要中间方法做一些工作。任意被检查到的由内部方法的抛出的异常必须在这个方法的 throws 子句中被指定。
优势 3 :分组和区分错误类型
因为所有在程序内部抛出的异常都是对象,异常的分组或分类是类继承的自然结果。在 Java 平台中一组相关异常类的例子是在 java.io 中定义的 IOException 和它的子类。 IOException 是最普通的 IO 异常管理类,并且它描述了在执行 I/O 操作时所发生的任意的错误类型。它的子类描述了一些特殊的错误。例如, FileNotFoundException 异常类代表不能在本地磁盘上找到一个文件。
一个方法能够编写特殊的异常处理器,使它能够处理非常特殊的异常。 FileNotFoundException 异常类没有子类,因此下面的异常处理器只能处理一种异常类型:
catch (FileNotFoundException e) {
...
}
一个方法能够基于它的分组或通过在 catch 子句中所指定的任何异常的超类的一般类型来捕获异常。例如,要捕获所有的 I/O 异常,而不管它们的具体类型,就可以在异常处理器中指定一个 IOException 参数:
catch (IOException e) {
...
}
这个处理器将捕获所有的 I/O 异常,包括 FileNotFoundException,EOFException 等等。你能够通过查询传递给异常处理器的参数找到发生错误的详细信息。例如,打印堆栈执行路线:
catch (IOException e) {
e.printStackTrace(); // output goes to Sytem.err
e.printStackTrace(System.out); // send trace to stdout
}
你甚至可以创建一个能够处理任意类型的异常的异常处理器:
catch (Exception e) { // a (too) general exception handler
...
}
Exception 类是 Throwable 类结构中的顶级类,因此,这个处理器将捕获除了那些被特定处理器捕获的异常以外的异常。你可能想你的程序是否都是这种处理异常的方法,例如,为用户打印错误消息并且退出。
但是,在大多数情况下,你需要异常处理器来尽可能的处理精确一些。原因是在处理器决定最好的恢复策略之前,必须做第一件是判断发生异常的类型是什么。在没有捕获特定错误的情况下,处理器必须有效的提供任意的可能性。 Exception 处理器是最一般的异常处理器,使用这个处理器使得代码捕获和处理更多的程序员没有预料到的错误倾向,从而使得处理器没有目的性。
象我们展示的一样,你能够创建异常组,并且用一般化的方式来处理异常,或者使用特定异常类型来区分异常并且用精确的方式来处理异常。
捕获和处理异常
这段向说明怎样使用异常处理器的三个组成部分- try,catch 和 finally 块来编写异常处理器。这段最后举一个例子,并且分析在不同的情况下发生了什么。
下面的例子定义和实现了一个叫做 ListOfNumbers 的类。在类的构造器中, ListOfNumbers 创建了一个 Vector ,它包含了从 0 到 9 的十个连续的整数。 ListOfNumbers 类也定义了一个叫 writeList 的方法,这个方法把这个数字列表写入一个叫做 OutFile.txt 的文本文件中。这个例子使用了在 java.io 中定义的输出类,这个类在 I/O :读写这一章中介绍。
// 注意 : 这样的设计,这个类不会被编译
import java.io.*;
import java.util.Vector;
public class ListOfNumbers {
private Vector victor;
private static final int SIZE = 10;
public ListOfNumbers () {
victor = new Vector(SIZE);
for (int i = 0; i < SIZE; i++) {
victor.addElement(new Integer(i));
}
}
public void writeList() {
PrintWriter out = new PrintWriter(
new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " +
victor.elementAt(i));
}
out.close();
}
}
这个例子中的第一行黑体字部分代码调用了一个构造器,这个构造器初始化一个文件输出流。如果这个文件不能被打开,这个构造器会抛出一个 IOException 异常。第二行黑体字部分代码调用一个 Vector 类的 elementAt 方法,如果它的参数值太小(小于零)或太大(大于 Vector 中当前所包含的元素数),那么它会抛出一个 ArrayIndexOutOfBoundsException 异常。
如果试图编译 ListOfNumbers 类,编译会打印一个有关被 FileWrite 构造器所抛出的异常的错误消息。这是因为构造所抛出的 IOException 异常是一个编译检查性异常,被 elementAt 方法抛出的 ArrayIndexOutOfBoundsException 异常是一个运行时异常,而 Java 编程语言只要求程序处理编译检查性异常,所以你只能获取一个错误消息。
现在随着对 ListOfNumbers 类的熟悉,并且知道异常是在程序中的什么地方抛出的,那么你就可以准备把异常处理器编写到 catch 块来处理那些异常。
怎样抛出异常
在你能够捕捉一个异常之前,在程序中的某个地方必须有抛出这个异常的代码在在。任何代码都可以抛出异常:它们可以你自己的代码,也可以是来自于别人所写的包中的代码(例如与 Java 平台一起提供的程序包),或者是 Java 运行时环境。不管抛出什么样的异常,都要使用 throw 语句把异常抛出。
你可能已经注意到, Java 平台提供了各种的异常类。所有的这些类都是 Throwable 类的子类,并且它们都允许程序来区分在程序执行期间所发生的各种类型的异常。
你也可以创建自己的异常类来描述你编写的类中所发生的问题。实际上,如果你是一个程序包的开发人员,你可能必须创建你自己的异常类的集合,以便于让你的用户来区分在你的程序包中发生的错误是来自己于 Java 平台还是其它的包。
你也可以创建异常链,异常链在 Java Standard Edition 1.4 中被引入。更多的信息,请看“异常链”这一节。
“ throw ”语句
所有的方法都使用“ throw ”语句来抛出一个异常。 Throw 语句需要一个单独 throwable 对象,这个对象是任意 Throwable 类的子类。如下类所示:
throw someThrowableObject;
让我们在程序的上下文中来看一下 throw 语句。下面的 pop 方法把来自于一个公共堆栈中的一个执行类给删除。这个方法从堆栈上面的元素,并且返回被删除的对象。
public Object pop() throws EmptyStackException {
Object obj;
if (size == 0) {
throw new EmptyStackException();
}
obj = objectAt(SIZE - 1);
setObjectAt(SIZE - 1, null);
size--;
return obj;
}
pop 方法检查堆栈上是否有元素。如果堆栈是空的(也就是说它的尺寸等于 0 ), pop 方法就会实例化一个新的 EmptyStackException 对象(它是 java.util 中的一个成员),并且抛出它。在这章的后面一节会解释怎样创建自己的异常类。对于现在,你所需要记住的是你只能抛出继承于 java.lang.Throwable 类的对象。
注意, pop 方法的声明中包含了一个 throws 子句。 EmptyStackException 是一个检查性异常,并且 pop 方法没有捕捉这个异常。因此,这个方法必须使用 throws 子名来声明它所抛出的异常的类型。
Throwable 类和它的子类
继承 Throwable 类的对象包括直接子类(直接继承于 Throwable 类的对象)和间接子类(继承于 Throwable 类的子类的对象)。下图说明了 Throwable 类的层次关系和最主要的一些子类。象你看到的一样, Throws 有两个直接的子类: Error 类和 Exception 类。
Error 类
当在 Java 虚拟机中发生动态连接失败或其它的定位失败的时候, Java 虚拟机抛出一个 Error 对象。典型的简易程序不捕获或抛出 Errors 对象。
Exception 类
大多数程序都抛出或捕获衍生于 Exception 类的对象。一个异常表明发生了一个问题,但它不是严重的系统问题。你编定的大多数程序将会抛出或捕获 Exceptions 对象(而不是 Errors 对象)。
在 Java 平台中 Exception 类有许多已经定义了的子类。这些子类说明所发生的异常的各种类型。例如, IllegalAccessException 异常类说明了不能找到一个特殊的方法; NegativeArraySizeException 异常类说明程序试图创建一个带有负尺寸的数组。
有一个特殊的 Exception 子类: RuntimeException 。这个子类是在程序运行期间在 Java 虚拟机内部所发生的异常。例如 NullPointerException 类就是一个运行时异常类,在一个方法试图通过一个 null 引用来访问一个对象的成员时会发生这个异常。在 Unchecked Exceptions---The Controversy 这一节中,我们会讨论为什么典型的程序不应该抛出运行时异常或 RuntimException 类的子类异常对象。
有争议性的未被检查的异常
因为 Java 编程语言不要求方法一定要捕获或列出运行异常或错误,所以程序员就可能被误导,编写只抛出运行时异常或者使所有的异常子类都继承于 RuntimException 的代码,这两种快捷方式允许程序员编写不用为编译错误而操心的代码,并且也不费神去指定或捕获任何异常。尽管这种方法看上去对程序员很方便,但它回避了捕获或指定必要的东西的意图,并且可能使使用你的类的程序员发生错误。
为什么设计者决定强制一个方法指定所有的在它的范围内可能被抛出的未检查异常呢?被一个方法抛出的任何异常都是方法公共编程接口的一部分。方法的调用者必须知道有关这个方法所抛出的异常,以便他们能够针对这些异常决定做什么。这些异常是编写方法的接口差不多,有它们的参数和返回值。
接下来你的问题可能是:如果它是这么好的说明了一个方法的 API ,包括它能抛出的异常,那么为什么不也指定运行时异常呢?运行时异常描述的问题是一个设计问题的结果,并且, API 的客户代码不能期望从出错的地方来恢复程序执行或用一些方法来处理它们。这些问题包括算法异常(例如被零除),指针异常(例如通过一个空的引用来访问一个对象),以及索引异常(例如试图通过一个越界的索引来访问一个数组)。运行时异常可能在
程序的任何地方发生,并且在一个典型的程序中可能有很多,因此,在每个方法中不得不添加运行异常来降低程序的透明度,这样,编译器不要求你指定或捕获运行时异常(尽管你可以)。
抛出运行时异常( RuntimeException )的一个公共案例就是在用户调用了一个错误的方法的时候。例如,一个方法检查它的参数是否有效,如果一个参数是空( null ),那么这个方法就可能抛出一个 NullPointerException 异常,这是一个不检查异常。
一般来说,不抛出运行时异常( RuntimeException )或不创建一个运行时异常( RuntimeException )的子类的原因是:人你不想为指定你的方法所能抛出的异常而操心。
一个使用异常的方针是:如果客户能够被期望从一个异常中得到恢复,那么就要使用检查性异常。如果一个客户对于从异常中恢复的程序不能做任何事,那么就可以使用不检查性异常。
第一、
try语句不能单独存在,可以和catch、finally组成 try...catch...finally、try...catch、try...finally三种结构,catch语句可以有一个或多个,finally语句最多一个,try、catch、finally这三个关键字均不能单独使用。
第二、
try、catch、finally三个代码块中变量的作用域分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
第三、
多个catch块时候,Java虚拟机会匹配其中一个异常类或其子类,就执行这个catch块,而不会再执行别的catch块。
第四
、throw语句后不允许有紧跟其他语句,因为这些没有机会执行。
第五、
如果一个方法调用了另外一个声明抛出异常的方法,那么这个方法要么处理异常,要么声明抛出。
异常的概念及分类异常时程序在编译或运行过程出现的例外,这些例外在有的可以避免有的却无法避免
检查异常
也称为
编译期异常
不可避免,必须进行异常处理,要不编译器报错
未检查异常
也称为
运行时异常
可以避免,不需要必须处理,通过修改代码解决
常见的运行异常
NullPointerException
空指针异常
ArithmeticException
算术异常
ArrayIndexOutOfBoundsException
数组下标越界异常
ClassCastException
类型转换异常
常见的编译异常
ParseException
解析异常
异常的处理方式
Java编译期异常必须要进行处理,否则Java源文件在编译时编译器会提示错误,且源文件无法成功编译
Java编译期异常的处理方式有两种
使用
try、catch、finally
关键字捕获异常 使用
throws
关键字声明抛出异常
使用try、catch、finally捕获异常
try{
//可能会出现异常的代码
}
catch(ParseException e)
{
//捕获执行的代码
}
finally
{
//不管是否发生异常都要执行的代码
}
自定义异常类
在开发中,可能需要自定义异常类 自定义异常根据继承的父类不同分为两类继承自
Exception
的自定义异常类
继承自
Exception
的自定义异常为编译期异常必须要进行 处理。
继承自
RuntimeException
的自定义异常类
继承自
RuntimeException
的自定义异常为运行时异常不需要进行特别的处理。