异常处理总结

        对于Java的异常情况,例如可能造成程序崩溃的错误输入,Java使用了一种称为异常处理(exception handing)的错误捕获机制。

一、处理错误

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

那么怎么解决这些错误呢?

        如果某个方法不能采用正常的途径他的任务,可以通过另一种路径退出方法。在这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。需要注意的是:这个方法将会立刻退出,并不返回正常值(或任何值),也不会调用这个方法的代码继续执行,取而代之的是,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exception handler)

异常分类

        在Java中,异常对象都是派生于(继承于)Throwable类的一个类实例,如果Java中内置的异常类不能满足要求,用户还可以创建自己的异常类。

下图是java异常层次结构的一个简化示意图

需要注意的是:

所有的异常都是由Throwable继承而来,但在下一层立即分解成两个分支:ErrorException

 

 Error类描述的错误:Java运行时系统的内部错误和资源耗尽错误

如果出现这种内部错误,除了通知用户,并尽力终止程序外,别无他法。

派生于RuntimeException的异常:

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

不是派生于RuntimeException的异常:

  • 试图超越文件末尾继续读取数据
  • 试图打开一个不存在的文件
  • 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在

二、捕获异常

        针对于可能出现异常的代码,进行抓捕

try {
    // 可能发生异常的代码
​
} catch (Exception e) {
    // 如果出现了一次,代码会立刻进入catch中
    // 在这儿解决抓捕到的异常
} finally {
    // 必须要执行的代码
}

如果try语句块中的任何代码抛出了catch子句中指定的一个异常类,那么:

  1. 程序将跳过try语句块的其余代码
  2. 程序将执行catch子句中的处理器代码

如果try语句块中的代码没有抛出任何异常,那么程序将跳过catch子句;

如果方法中的任何代码抛出了catch子句中没有声明的一个异常类型,那么这个方法就会立即退出。

代码示例:

public class DemoException extends Throwable {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个整数:");
        int num = 0;
        try {
            num = scanner.nextInt();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("num = " + num);
    }
}

finally语句

        无论是否有异常发生,如果我们都希望执行一些语句,例如清理工作,怎么写?

public static void main(String[] args) {
    try {
            process1();
            System.out.println("END");
        } catch (UnsupportedEncodingException e) {
            System.out.println("Bad encoding");
            System.out.println("END");
        } catch (IOException e) {
            System.out.println("IO error");
            System.out.println("END");
    }
}

上述代码无论是否出现异常,都会执行“System.out.println("END");”语句,消除重复语句执行,代码可改写为:

public static void main(String[] args) {
    try {
            process1();
        } catch (UnsupportedEncodingException e) {
            System.out.println("Bad encoding");
        } catch (IOException e) {
            System.out.println("IO error");
        } finally {
            System.out.println("END");
    }
}

注意 finally 有几个特点:

1. finally 语句不是必须的,可写可不写;

2. finally 总是最后执行。

如果没有发生异常,就正常执行 try { ... } 语句块,然后执行 finally 。如果发生了异常, 就中断执行 try { ... } 语句块,然后跳转执行匹配的 catch 语句块,最后执行 finally 。

可见, finally 是用来保证一些代码必须执行的。

三、抛出异常

        EOFException异常的描述是:“指示输入过程中意外遇到EOF”。这正是要抛出的异常。下面是抛出这个异常的语句:

    throw new EOFException();
//或者,也可以是
    var e = new EOFException();
    throw e;
//下面将这些代码放在一起:
    String readData(Scanner in) throws EOFException
    {
        ……
        while(...)
        {
            if (!in.hasNext())// EOF encountered
            {                
                if (n < len)

                 throw new EOFException();
            }
                ……
        }
        return s;
    }


        EOFException类还有一个带一个字符串参数的构造器。可以很好地利用这个构造器,更细致地描述异常。

String gripe ="Content-length:"+ len +",Received:"+ n;
throw new EOFException(gripe);

在前面已经看到,如果一个已有的异常类能够满足你的要求,抛出这个异常非常容易。在这种情况下:
1.找到一个合适的异常类。
2.创建这个类的一个对象。
3.将对象抛出。
一旦方法抛出了异常,这个方法就不会返回到调用者。也就是说,不必操心建立一个默认的返回值或错误码。

四、创建异常类(自定义异常)

        需要做的只是定义一个派生于Exction的类,或者派生于Exception的某个子类,如IOException。习惯做法是,自定义的这个类应该包含两个构造器,一个是默认的构造器,另一个是包含详细描述信息的构造器(超类Throwable的tostring方法会返回一个字符串,其中包含这个详细信息,这在调试中非常有用)。
 

class FileFormatException extends IOException
{
    public FileFormatException(){}    
    public FileFormatException(String gripe)    
    {    
        super(gripe);
    }
}
//现在,就可以抛出你自己定义的异常类型了。
String readData(BufferedReader in) throws FileFormatException
{
    ……
    while(……)
    {
        if (ch == -1) // EOF encountered
        {
            if (n < len)
                throw new FileFormatException();
        }
        ……
    }
        return s;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

simpleHan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值