java一个疑问,为啥有些异常throw出去需要在函数头用throws声明,一些就不用。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java一个疑问,为啥有些异常throw出去需要在函数头用throws声明,一些就不用。相关的知识,希望对你有一定的参考价值。

throw new IllegalStateException(".");
不用在函数头声明throws IllegalStateException
throw new IOException(".");
不声明throws编译不通过
两种情况
1、Integer.parseInt("1");这个java.lang包里面的方法,有throws NumberFormatException,但我调用的时候不用catch
2、
public final DefaultIoFilterChainBuilder getFilterChain()
throw new IllegalStateException(
"Current filter chain builder is not a DefaultIoFilterChainBuilder.");

这个方法,我不用声明throws照样可以编译通过

所谓checked exception和runtime exception

checked exception告知外部用户此方法在某些情况下可能抛出这个错误,你应该捕获并处理错误以便程序在可能的情况下能够继续运行下去(当然你也可以通过throws声明将异常再往上层暴露,但终究有一层是要去catch这个异常的)。这些错误往往是可预期而且可以作为异常流来处理的。checked exception作为语法上的一种强制措施让你在代码编译阶段就必须对异常进行处理。

比如IOException,当你打开、读取、写入文件时可能抛出这个错。你可以捕获并提示最终用户『文件操作失败,请重试』等信息,而不是任由它抛到JVM中导致当前线程挂掉。

而runtime exception可能产生于运行时的一些不可预知的时刻,而且往往产生后没有有效的手段处理,因此不需要强制对其进行声明和捕获。

你可以认为checked exception就是要强制你去处理这个异常(不管你throws多少层,你终归要在某个地方catch它);而runtime exception则没有这个限制,你可以自由选择是否catch。

=== 分割线 ===

事实上我觉得checked exception是一个非常2B的设计,很多语言中都没有这种设计。API设计并不需要这种强制处理的错误,可以通过封装返回值来做到更友好的处理。
单说Java的变种Groovy(确切来说不能叫变种,不过语法也相似)就没有这么蛋疼的设计;Scala也同样没有。追问

是在哪里声明checked exception的,还是限定只有几种的。
自己定义的异常可以声明这种的吗,还是只能继承runtime

追答

你继承自RuntimeException就是runtime的exception 直接继承自Exception就是checked exception

参考技术A 因为IOException是非运行时异常, 无法用程序去显示处理(这个解释起来比较绕口), 但是你只要知道这种非运行时异常不是你程序的问题, 而是外部的问题, 比如你读文件, 压根就没有这个文件, 就会出现IOException, 所以说, 这种非运行时异常不是你修改程序就能解决的问题(意思就是不怪你, 怪找不到那个文件)

java中要求非运行时异常必须要通过函数抛出, 这种非运行时异常为什么要通过函数来抛出, 是为了让编译器去帮你定位这些异常是出现在哪些代码段里, 从而告诉你这里你必须try和catch....., 注意是必须, 如果你不trycatch, 那么编译都不会通过., 所以非运行时异常也叫做可检测异常

IllegalStateException是运行时异常, 就是只有在运行时才有可能出现的异常, 是你程序写得有问题, 需要你通过修改程序来避免,编译器是无法帮助你的, 即使你不去trycatch, 编译器也不会报错, 所以编译器也就没有要求你一定要在函数处抛出这类异常

我语文不太好, 反正希望你能理解我的意思 ......................追问

也谢谢你的回答,大概懂了

参考技术B 异常分两种,一种是可抓可不抓的,一种是必须抓的。可抓可不抓的异常就可以不用写throws,必须抓的异常那就必须要写throws了。 参考技术C throws 是说明本方法会抛出异常

throw 是真的要抛出异常的时候用。

方法内,全catch可不抛出。但,如果是实现接口、继承抽象类,则要根据原方法定义一致。
参考技术D 请举个不用的例子~追问

第一个就是不用的throw new IllegalStateException(".");

异常处理时为什么有些异常throw出去需要在函数头用throws声明,有些就不用

Excepiton分两类:checked exception、runtime exception;直接继承自Exception就是checked exception,继承自RuntimeException就是runtime的exception。

你可以简单地理解checked exception就是要强制你去处理这个异常(不管你throws多少层,你终归要在某个地方catch它);而runtime exception则没有这个限制,你可以自由选择是否catch。

那些强制异常处理的代码块,必须进行异常处理,否则编译器会提示“Unhandled exception type Exception”错误警告。

举例子:

IndexOutOfBoundsException是RuntimeException的一种,方法体内手动throw了一个异常,但是rangeCheckForAdd()定义处不用写 throws……
而getName()则必须要throws

private static void rangeCheckForAdd(int index) 
    // IndexOutOfBoundsException是RuntimeException的一种,方法体内手动throw了一个异常,test7_throw()定义处不用写 throws
    int size = 3;
    if (index > size || index < 0) 
        throw new IndexOutOfBoundsException();
    


private static void getName() throws IOException  // 这里的throws必须写
    // FileNotFoundException是checkedException的一种,直接继承自Exception
    // 那些强制异常处理的代码块,必须进行异常处理,否则编译器会提示“Unhandled exception type Exception”错误警告
    throw new FileNotFoundException();

 

以上是关于java一个疑问,为啥有些异常throw出去需要在函数头用throws声明,一些就不用。的主要内容,如果未能解决你的问题,请参考以下文章

java中带有throws的方法中一定要加throw吗?

201671010145 2016-2017《Java程序设计》JAVA语言中,异常处理有哪几种方式?

java 19 - 6 throws的方式处理异常

java异常 throw和try-catch的关系

Java中的异常处理

异常-throws的方式处理异常