什么是运行时异常?什么是已检查/未检查异常?错误和异常之间的区别是什么?为什么会有这么多类型?相反,Java 可以简单地遵循一个简单的设计(只尝试捕获所有类型)来处理程序中的异常情况吗?
什么是运行时异常?什么是已检查/未检查异常?错误和异常之间的区别是什么?为什么会有这么多类型?相反,Java 可以简单地遵循一个简单的设计(只尝试捕获所有类型)来处理程序中的异常情况吗?
由于我是一名新的Java开发人员,我也遇到了区分和处理不同类型异常的一些困难。这就是为什么我在这个主题上做了一个简短的笔记,每当我感到困惑时,我就会浏览它。以下是带有Throwable
类层次结构图像的内容:
[图片来源:JavaTpoint]。
这里有三个关键类需要记住:Throwable
、Exception
和Error
。在这些类中,Exception
可以分为两种类型:"Checked Exception"和"Unchecked Exception"。
Checked Exception:
Throwable
除了RuntimeException
和Error
。 try/catch
来处理它们或在函数签名中指出它们,并强制我们在调用方处理它们。IOException
、SQLException
等。Unchecked Exception:
RuntimeException
的类被称为未检查异常。ArithmeticException
、NullPointerException
、ArrayIndexOutOfBoundsException
等。ArithmeticException
,可以通过对除数进行简单的检查来避免。同样,我们可以通过简单地检查引用:if (object != null)
甚至使用更好的技术来避免NullPointerException
。错误:
Error
指的是没有被try/catch
处理的无法恢复的情况。OutOfMemoryError
、VirtualMachineError
、AssertionError
等。为什么有这么多类型?
除了Stephen C的回答外,我想说:
在Java中,异常处理是一种相对昂贵的操作。我们不应该将所有异常情况都放在try/catch
块中。过度使用try/catch
可能会影响程序性能。
总之,应尽可能以编程方式处理Exception
。另一方面,我们无法处理Error
,因此这可能是有许多类型异常的某些逻辑原因。
Error
不可捕获并不是严格正确的。没有人阻止你编写 try { sometching(); } catch(Error e) { }
,但实际上这样做是一个坏主意(有关详细信息,请参见 @TofuBeer 的答案)。 - Qw3ryThrowable是所有异常的顶级父类。在Throwable下面有Error和Exception,在Exception下面有RuntimeException。
Java有两种类型的异常 - checked异常和unchecked异常。编译器强制执行checked异常(你必须在throws子句中声明它们并最终捕获它们)。未强制执行unchecked异常以用于捕获或在throws子句中声明。
Throwable的存在是为了成为所有异常类型的父类。除非你真的非常了解自己在做什么,否则永远不要声明你抛出Throwable或者捕获它。
Error表示运行时环境出现问题,这些问题可能使你的程序无法恢复,比如格式错误的类文件或虚拟机内存耗尽。除非你真的知道自己在做什么,否则不要捕获Error。
Exception作为所有非程序员错误的根源(参见RuntimeException以了解其"例外"情况),比如因磁盘空间满而无法创建文件。不应该抛出、throws或捕获Exception。如果必须捕获Exception,请确保你知道自己在做什么。
RuntimeException用于指示所有程序员错误,比如超过数组末尾或在空对象上调用方法。这些都是你应该修复的错误,使它们不会抛出异常 - 表明你作为程序员,出了问题。同样,除非你知道自己在做什么,否则不应该捕获这些异常。
TofuBeer的回答清晰地解释了异常类的含义。
为什么有这么多类型?Java为什么不遵循一个简单的设计(只需尝试/捕获所有类型)来处理程序中的异常情况呢?
为什么?因为它们是必要的!如果没有这4个类,按广泛类别处理异常将是不切实际的。
Error
类,你如何捕获“所有致命的JVM错误”?Exception
类,你如何捕获“所有非JVM致命错误的异常”?RuntimeException
类,你如何捕获“所有未经检查的异常”?Checked和Unchecked异常的区别:
Checked和Unchecked异常有很多区别,但所有的区别都源于一个基本考虑,即编译器是否可以解决异常。
需要记住的要点是:
[1] Checked异常意味着编译器检查异常。这意味着编译器强制要求使用try-catch块或throws关键字来处理此类异常。
[2] Unchecked异常是指编译器不提供任何强制规定的异常,因为开发人员可以通过编码/编程来解决它们,控制流是可控的,例如ArithmeticException、NullPointerException ArrayIndexOutOfBoundsException、IllegalArgumentException等。
我称之为“异常身份测试”,您可以从Java文档中随机选择任何异常,并问它一个问题。“嘿,异常!你能通过编程解决吗?”
如果异常回答YES,那么它就是一个Unchecked异常,因为可以通过更改代码或解决某些计算错误等方式来解决它。
另一方面,如果异常信息显示“否”,那么这就是已检查异常。在已检查异常中,控制流会跳出我们的代码,例如如果有人更改了数据库密码或拔掉了网络电缆,连接超时(ConnectException),某些资源未找到(FileNotFoundException、ClassNotFound),SQLException,InvocatonTargetException等等。这些异常无法通过编程解决。这篇文章以清晰简洁的方式总结了Checked和Unchecked异常。
Checked Exceptions: 已检查异常是在编译时可以检测、识别和检查的异常。如果代码块抛出了一个已检查异常,那么方法必须处理该异常或使用throws
关键字指定该异常。
示例:
public void testDB() throws ClassNotFoundException, SQLException
{
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Driver Loaded");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/selenium","root","root");
System.out.println("Connected to MySQL DB");
}
我们需要使用throws
指定异常列表或使用try-catch{}
块。我在下面的程序中演示了throws
的用法。
Unchecked Exceptions: 未检查异常不会在编译时进行检查。Java异常在Error
和RuntimeException
类下是未经检查的异常,而在throwable下的所有其他内容都是已检查的。
运行时异常提供了灵活性,避免了捕获和声明异常的繁琐过程。
RuntimeException
是一个不好的主意®。请小心使用,不要仅仅将其作为一种捷径。 - user4229245Exceptions are two types in java:
1. **Checked Exception: The exceptions which are checked by compiler.
2. Unchecked Exception: The exceptions which are not checked by compiler at run time.