java学习之路---异常

如果一个用户在运行程序期间,由于程序的错误或一些外部环境的影响造成用户数据的丢失,用户就有可能不再使用这个程序了。为了避免这类事情发生,至少做到以下几点:

  • 向用户通告错误;
  • 保存所有的工作结果;
  • 允许用户以妥善的形式推出程序。

对于异常情况,Java使用一种称为异常处理(exception handing)的错误捕获机制处理。

处理错误
假设在一个Java程序运行期间出现了一个错误。这个错误可能是由于文件包含了错误信息,或者网络连接出现问题造成的,也有可能是因为使用无效的数组下标,试图使用一个没有被赋值的对象引用造成的。
由于出现错误而使得某些操作没有完成,程序应该:

  • 返回到一种安全状态,并让用户执行一些其他命令;
  • 允许用户保存所有操作的结果,并以妥善的方式终止程序
    1.用户输入域错误
    2.设备错误
    3.物理限制
    4.代码错误
    在Java中,如果某个方法不能够采用正常的途径完成它的任务,就可以提供另外一个路径退出方法。在这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。这个方法将会立刻退出,并不返回任何值。取而代之的是,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exception handler)。异常具有自己的语法和特定的继承结构。

1.异常分类
Java中,异常对象都是派生于Throwable类的一个实例。如果Java中内置的异常不能够满足需求,用户可以创建自己的异常类。
在这里插入图片描述
所有的异常都是由Throwable继承而来,但在下一层立即分解为两个分支:Error和Exception。
Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。引用程序不应该抛出这种类型的对象。很少出现。
在Java中,需要关注Exception层次结构。又划分了两个分支,由程序错误导致的异常属于RuntimeException;而程序本身没问题,由于像I/O错误这类问题导致的异常属于其他异常。
派生于RuntimeException的异常包含下面几种情况:

  • 错误的类型转换
  • 数组访问越界
  • 访问null指针

不是派生于RuntimeException的异常包括:

  • 试图在文件尾部后面读取数据
  • 试图打开一个不存在的文件
  • 试图根据给定字符串查找Class对象,而这个字符串表示的类并不存在。
    “如果出现RuntimeException异常,那么就一定是你的问题”
    Java中将派生于Error类或RuntimeException类的所有异常称为非受查(unchecked)异常,其他的异常称为受查(checked)异常。

2.声明受查异常
一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误。例如:一段读取文件的代码知道有可能读取的文件不存在,或者内容为空,因此,试图处理文件的信息就需要通知编译器可能会抛出IOException类的异常
方法应该在首部声明所有可能抛出的异常。下面是标准类库中的FileInputStream类的一个构造器声明:

 **public FileInputStream(String name)  throws  FileNotFoundException**

这个声明表示这个构造器将根据特定的String参数产生一个FileInputStream对象,但也有可能抛出一个FileNotFoundException异常。如果发生异常,构造器将不会初始化一个新的FileInputStream对象,而是抛出一个FileNotFoundException类对象。
自己编写方法时,在遇到以下4种情况应该抛出异常:

  1. 调用一个抛出受查异常的方法,例如,FileInputStream构造器。
  2. 调用运行过程中发现错误,并且利用throw语句抛出一个受查异常
  3. 程序出现错误,例如,a[-1]=0会抛出一个ArrayIndexOutOfBoundsException这样的非受查异常
  4. Java虚拟机和运行时库出现的内部错误。

对于那些可能被他人使用的Java方法,应该根据异常规范在方法的首部声明这个方法可能抛出的异常。

class  MyAnimation
{
    .....
    public  Image  loadImage(String  s)    throw  IOExpection
    {
       .....
       }
}

如果一个方法可能抛出多个受查异常类型,那么就必须在方法的首部列出所有的异常类。每个异常类之间用逗号隔开。

class  MyAnimation
{
   .......
   public Image  loadImage(String s)   throw  FileNotFoundException,EOFException
   {
     .....
     }
}

不应该声明从RuntimeException继承的那些非受查异常

class  MyAnimation
{
   ........
   void  drawImage(int i)   throws  ArrayIndexOutOfBoundsException    //错误
   {
     ......
     }
}

这种运行时错误完全在我们的控制之下。如果特别关注数组下标引发的错误,就应该将更多的时间花费在修正程序的错误上,而不是说明这些错误发生的可能性上。
总之,一个方法必须声明所有可能的受查异常,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。如果方法没有声明所有的可能发生的受查异常,编译器就会发出一个错误消息。
如果类中的一个方法声明将会抛出一个异常,而这个异常是某个特定类的实例时,则这个方法就又可能抛出这个类的异常,或者这个类的任意一个子类的异常。例如,FileInputStream构造器声明将有可能抛出一个IOException异常,然而并不知道具体是那种IOException异常。可能是IOExecption异常,也有可能是其子类的异常,FileNotFoundException。

3.如何抛出异常
一个名为readData的方法正在读取一个首部具有下列信息的文件:

 Content-length:  1024

然而读到733个字符之后文件就结束了。我们认为这是一种不正常的情况,希望抛出一个异常。
首先要决定应该抛出什么类型的异常。将上述异常可以认为IOException:“在输入过程中,遇到一个未预期的EOF后的信号” 下面是抛出这个异常的语句:

  throw  new  EOFException();

或者

 EOFException  e=new  EOFException();
 throw e;

下面将这些代码放在一起:

String  readData(Scanner  in) throws  EOFException
{
  ......
  while(.....)
  {
      if(!in.hasNext())   //EOF encountered
      {
        if(n<len)
          throw  new  EOFExecption();
          }
          ......
          }
          return  s;
}

对于一个已经存在的异常类,将其抛出非常容易。

  1. 找到一个合适的异常类
  2. 创建这个类的一个对象
  3. 将对象抛出

一旦方法抛出了异常,这个方法就不可能返回到调用者。不必为返回的默认值或错误代码担忧。

4.创建异常类

在程序中,可能会遇到任何标准异常类都没有能够充分地描述清楚的问题。我们需要做的只是定义一个派生于IOExecption的类,或者派生于Exception子类的类。例如,定义一个派生于IOException的类,应该包含两个构造器,一个是默认构造器;另一个是带有详细描述信息的构造类。

   class  FileFormatException  extends  IOException
   {
      public  FileFormatException() {}
      public  FileFormatExcepton(String  gripe)
      {
          super(gripe);
          }
}

现在就可以抛出自己定义的异常类型了

String  readData(BufferedReader  in)  throws  FileFormatException
{
    .........
    while(.....)
    {
       if(ch==-1)   //调用异常
       {
         if(n<len)
         throw  new  FileFormatException();
         }
         ......
         }
         return  s;
}
API  java.lang.Throwable  1.0
Throwable()
构造一个新的Throwable对象,这个对象没有详细的描述信息
Throwable(String  message)
构造一个新的Throwable对象,这个对象带有特定的详细描述信息。
String  getMessage()
获得Throwable对象的详细描述信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值