当前位置: 首页 > news >正文

java异常处理(Exception handing)机制

一.异常:

1.1异常分类:

异常对象都是派生于throwable类的实例:

  • Error类说明java运行时存在内存错误或资源耗尽错误,出现这类错误,除了告诉用户,别无他法
  • Exception是需要关注的;它又分为RuntimeExceptionIOException

 

如果出现了RuntimeException,那么一定是你自己的问题

 

Error类或RuntimeException类的所有异常称为非受查(uncheck)异常,其他的异常成为受查(check)异常

 

1.2受查异常:

需要记住在以下情况中应该抛出异常:

  • 调用一个抛出受查异常的方法时,如:FileInputSteam构造器
  • 程序运行时发现错误,利用throw抛出一个受查异常
  • 程序出现错误时,如:数组越界(ArrayIndexOutOfBoundsException)
  • java虚拟机和运行时库内出现的内部错误

 

如果出现前两种异常之一,则必须告诉程序员调用这个方法可能会出现的异常,如果没有处理器捕获,当前执行的线程就会结束

对于可能被其他人调用的方法,应根据异常规范(exception specification),在方法首部声明者个可能的的异常:

class MyAnimation
{
    . . .
    public Image loadImage(String s) throws IOException
    {
        . . .
    }
}    

但是,无需声明java的内部错误,我们无法控制Error.

同样,不应该声明从RuntimeException继承的非受查异常:

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

这些异常完全在我们的控制之下,与其去说明异常,我们更应该将精力花费在修改程序上

 

总之,一个方法必须声明可能抛出的受查异常,非受查异常要么是错误(Error),要么是可以避免发生的RuntimeException

 

注意:

  • 如果在子类中覆盖了一个父类的方法,子类声明的受查异常不可比父类的方法中声明的异常更为通用.
  • 如果父类方法没有抛出任何受查异常,那么子类也不能抛出任何受查异常

 

1.3抛出异常:

对于一个已知的异常类:

1).找到一个合适的异常类

2).创建这个类的对象

3).将对象抛出

 

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

 

一旦方法抛出了异常,该方法就不会返回给调用者,我们就不必再为返回的默认值或错误代码担忧  

 

 

1.4创建异常:

 

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

 

习惯上,定义的类包含两个构造器,一个是无参构造器,另一个是带有详细描述的构造器(父类Throwable的toString方法将会打印出详细信息)  

 

自定义构造器代码例:

String readData(BufferedReader in) throws FileFormatException
{
    . . .
    while (. . .)
    {
        if (ch == -1) 
        {
            if (n < len)
            throw new FileFormatException();
        }
        . . .
    }
    return s;
}

 

 

1.5.1捕获异常:

try
{
    code
    more code
    more code
}
catch (ExceptionType e)
{
    handler for this type
}

如果在try语句块中抛出了在catch语句块中说明的异常类,那么:

  • 程序将跳过try语句块其余的代码
  • 执行catch子句中的处理代码(如果在try中没有抛出任何异常,跳过catch子句)

如果方法中任何代码抛出了在catch中没有声明的异常,那么这个方法会立即退出

 

代码演示说明:

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();
    }
}

read方法可能抛出一个IOException,这将会跳出while循环,进入catch子句,并声称一个栈轨迹(stack trace)

通常,最好的办法是什么也不做,而是将异常传给调用者,让调用者去操心怎么做,如果采用这种方式,就必须声明这个方法可能会抛出的异常:public void read(String filename) throws IOException

 

 

1.5.2捕获多异常:

 

try
{
    code that might throw exceptions
}
catch (FileNotFoundException e)
{
    emergency action for missing files
}
catch (UnknownHostException e)
{
    emergency action for unknown hosts
}
catch (IOException e)
{
    emergency action for all other I/O problems
}

 

在JKD1.7之后,可以这样捕获异常:

catch (FileNotFoundException | UnknownHostException e)
{
    emergency action for missing files and unknown hosts
}

注意:捕获多个异常时,异常的变量为final

 

捕获多个异常不仅会使代码看起来更简洁,而且会使代码运行效率更快

 

1.6finally语句:

不管是否有异常被捕获,finally子句都必将被执行:

InputStream in = new FileInputStream(. . .);
try
{
    // 1
    code that might throw exceptions
    // 2
}
catch (IOException e)
{
    // 3
    show error message
    // 4
}
finally
{
    // 5
    in.close();
}
// 6

1).代码没有抛出异常.执行:1.2.5.6

2).抛出一个可以在catch中捕获的异常:

  • 如果catch没有抛出异常,执行:1.3.4.5.6
  • 如果catch子句抛出一个异常,执行:1.3.5(异常被抛会给方法调用者)

3).代码抛出一个异常,但没有catch可以捕获到,执行:1.5

 

因此,finally子句是无论如何都会执行的,下面的例子有一种令人意外的结果:

public static int f(int n)
{
    try
    {
        int r = n * n;
        return r;
    }
    finally
    {
        if (n == 2) return 0;
    }
}

调用f(2),try子句return结果r = 4,但是finally必然执行,return 0并覆盖 r = 4.

 

转载于:https://www.cnblogs.com/nothingAJ/p/6677901.html

相关文章:

  • 四则运算 web 版
  • 201521123030 《Java程序设计》第7周学习总结
  • Ajax异步封装
  • 闭包与循环
  • iOS 字符串 MD5
  • 查看linux源代码的在线网站
  • Android入门:MVC模式(中)
  • Oracle中INSTR函数与SQL Server中CHARINDEX函数
  • 沟通和编程一样,也是一门艺术系列5(沟通的方向)
  • CSS实现Tab布局
  • Spring定时任务的几种实现(转)
  • Android Handler使用
  • django-rest-framework学习之Requests and Responses--2017年4月13日
  • LightOJ1245 Harmonic Number (II)
  • Hnoi-2017 滚粗记
  • JS 中的深拷贝与浅拷贝
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • angular2 简述
  • EventListener原理
  • magento 货币换算
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • php ci框架整合银盛支付
  • Python - 闭包Closure
  • tab.js分享及浏览器兼容性问题汇总
  • vue数据传递--我有特殊的实现技巧
  • webpack入门学习手记(二)
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 技术胖1-4季视频复习— (看视频笔记)
  • 简单数学运算程序(不定期更新)
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 马上搞懂 GeoJSON
  • 前端临床手札——文件上传
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 【云吞铺子】性能抖动剖析(二)
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #define,static,const,三种常量的区别
  • #mysql 8.0 踩坑日记
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (7)STL算法之交换赋值
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (定时器/计数器)中断系统(详解与使用)
  • (二十四)Flask之flask-session组件
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (篇九)MySQL常用内置函数
  • (算法二)滑动窗口
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (转)Android学习笔记 --- android任务栈和启动模式
  • ***利用Ms05002溢出找“肉鸡
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全