原文地址:http://literatejava.com/exceptions/checked-exceptions-javas-biggest-mistake/

仅供参考,毕竟我四级都没过

Checked exceptions have always been a controversial feature of the Java language.

检查型异常一直是Java语言当中有争议的特性

Advocates claim they ensure checking & recovery from failures. Detractors say “catch” blocks can almost never recover from an exception, and are a frequent source of mistakes.

支持者表示对于异常总是能检查到并恢复。而反对者则说catch到的那些代码块几乎不能从Exception中恢复,并且常常产生其他错误。

Meanwhile, Java 8 and lambdas are here. Are checked exceptions becoming obsolete in the Java world?

现在,Java8和lambdas来了。那么检查型异常是否已经变的过时了?

The Intent of Checked Exceptions

检查型异常的用途

In the mid 90’s, James Gosling at Sun came up with a new language.

在90年代中期,Sun公司的James Gosling提出了一种新的语言

At the time, C++ programming required every single function return to be checked for error. He decided there had to be a better way, and built the concept of “exceptions” into Java.

当时,C++程序要求检查每个方法的返回错误。James觉得应该会有更好的方式,然后就将“异常”的观念带到了Java当中

The intent of checked exceptions was to locally flag, and force developers to handle, possible exceptions. Checked exceptions have to be declared on a method signature, or handled.

检查型异常的目的是在本地做标记,然后强迫程序员去处理可能发生的异常,你必须选择在方法定义上声明这个异常或者直接处理

This was intended to encourage software reliability & resilience. There was an intent to “recover” from contingencies – predictable outcomes other than success, such as InsufficientFundsException on attempting a payment. There was less clarity, as to what “recovery” actually entailed.

这是为了加强软件的可靠性和弹性。它希望可以从意外当中“恢复”到除了成功之外的某种可预见的结果,比如在支付中抛出InsufficientFundsException 异常。但是“恢复”真正带来了什么,却一点都不明确。

Runtime exceptions were also included in Java. Since null pointers, data errors, and illegal states/ accesses could occur anywhere in code, these were made subtypes of RuntimeException.

运行期异常也被包括在了Java当中,包括空指针,数据错误和非法的访问等都可能发生在程序的任何地方。

Runtime exceptions can be thrown anywhere, without requiring to be declared, and are much more convenient. But would it be correct to use them instead?

不需要先声明就可以在任意地方抛出运行期异常,非常方便。但是这样是不是真的是对的?

The Drawbacks

缺点

The crucial point here, is that runtime & checked exceptions are functionally equivalent. There is no handling or recovery which checked exceptions can do, that runtime exceptions can’t.

关键点在于,运行时异常和检查型异常在功能上是相似的。不会有检查型异常可以处理和恢复但是运行期异常不能的情况。

The biggest argument against “checked” exceptions is that most exceptions can’t be fixed. The simple fact is, we don’t own the code/ subsystem that broke. We can’t see the implementation, we’re not responsible for it, and can’t fix it.

检查型异常最大的争论点在于大多数异常并不能被修复。事实上,我们拿不到有问题的代码或者子系统。我们看不到实现,我们不能处理它们,也无法修复它们。

Particularly problematic were the areas of JDBC (SQLException) and RMI for EJB (RemoteException). Rather than identifying fixable contingencies as per the original “checked exception” concept, these forced pervasive systemic reliability issues, not actually fixable, to be widely declared.

特别有问题的是JDBC的SQLException和EJB当中RMI部分的RemoteException异常。这些被强迫关注,普遍存在的系统问题(事实上是不能修复的),被到处声明,而不是按照最初“检查型异常”的想法去识别可以修复的异常。

For any method, the possibility of failure includes all sub-methods called by it. Potential failures accumulate up the call tree. Declaring these on method signatures no longer offers a specific & local highlight for the developer to watch for – declared exceptions spread throughout the call tree.

对于任何方法,错误可能发生在它调用的任何一个子方法。这些错误都堆积在访问树上。可是在方法声明上不会特意标识这些异常。

Most EJB developers have experienced this – declared exceptions become required on methods through the tier, or entire codebase. Calling a method with different exceptions requires dozens of methods to be adjusted.

大多数EJB开发者都有这样的经历-通过层级或是代码库调用方法必须声明异常。调用一个会产生不同异常的方法可能需要调整更多的方法。

Many developers were told to catch low-level exceptions, and rethrow them again as higher (application-level) checked exceptions. This required vast numbers – 2000 per project, upwards – of non-functional “catch-throw” blocks.

很多开发者会被要求捕获低级的异常,然后作为更高级的检查型异常再次抛出。这会造成一个项目中,可能产生2000个没什么用的“catch-throw”代码块。

Swallowing exceptions, concealing the cause, double logging, and returning ‘null’/ uninitialized data all became common. Most projects could count 600+ mis-coded or outright errors.

Swallowing exceptions,concealing the cause,double logging以及返回null或者未初始化数据都是很常见的错误。大多数项目可能有多达600多个错误代码。

Eventually, developers rebelled against the vast numbers of “catch” blocks, and the source of error these had become.

所以,开发人员反对大量的“catch”代码块,并且这些代码块已经成为错误的来源。

Checked Exceptions – incompatible with Functional Coding

检查型异常-与函数编程相矛盾

And then we get to Java 8, with its new functional programming features – such as lambdas, Streams, and function composition.

现在,我们有了Java8,它带来了新的特性-有lambdas表达式,streams和函数式编程。

These features are built on generics – parameter & return types are genericized, so that iteration & stream operations ( forEachmapflatMap) can be written which perform a common operation, regardless of item type.

这些特性建立在泛型上-参数和返回值类型是通用的,所以编写的iteration和stream(forEach,mapflatMap)可以执行常见操作,而不用管它的类型。

Unlike data types, however, declared exceptions can’t be genericized.

但是与数据类型不同,声明式异常不能被通用化。

There is no possibility in Java to provide a stream operation (like, for example,  Stream.map) which takes a lambda declaring some checked exception, & transparently passes that same checked exception to surrounding code.

Java不可能提供一个Stream操作(比如Stream.map),用一个lambda表达式声明检查型异常,然后显式的将同样的检查型异常传递给其他代码。

This has always been a major points against checked exceptions – all intervening code, between a throw and the receiving “catch” block, is forced to be aware of exceptions.

这是反对检查型异常主要的点-所有位于throw和catch块的代码,都被迫要注意可能发生的异常。

The workaround, of “wrapping” it in a RuntimeException, conceals the original type of the exception – rendering the exception-specific “catch” blocks envisaged in the original concept useless.

在RuntimeException中,封装了它的方法,隐藏了异常的原始类型-使原始概念中异常的catch块变的无用。

Finally we can capture Java’s new philosophy in a nutshell, by noting that none of the new “functional interfaces” in Java 8 declare checked exceptions.

我们了解了Java新的理念,Java8中没有新的“功能接口”声明了检查型异常。

Conclusion

结论

Exceptions in Java provided major benefits in reliability & error-handling over earlier languages. Java enabled reliable server & business software, in a way C/ C++ never could.

Java的异常比早起的语言更可靠,更强的错误处理能力。

Checked exceptions were, in their original form, an attempt to handle contingencies rather than failures. The laudable goal was to highlight specific predictable points (unable to connect, file not found, etc) & ensure developers handled these.

检查型异常,尝试去处理意外情况而非错误。优点是明确可预见的部分(连接不上,文件找不到等等),并确保开发者处理这些问题。

What was never included in the original concept, was to force a vast range of systemic & unrecoverable failures to be declared. These failures were never correct to be declared as checked exceptions.

最初的设想中并不包括声明大量系统性的和不能恢复的错误。这些错误不会被声明为检查型异常。

Failures are generally possible in code, and EJB, web & Swing/AWT containers already cater for this by providing an outermost “failed request” exception-handler. The most basic correct strategy is to rollback the transaction & return an error.

但代码通常会发生错误,EJB、Web和 Swing/AWT容器通过提供最外层的“失败请求”异常来处理发生的问题。最基本的策略是回滚事务然后返回一个错误。

Runtime exceptions allow any exception-handling possible with checked exceptions, but avoid restrictive coding restraints. This simplifies coding & makes it easier to follow best practice of throw early, catch late where exceptions are handled at the outermost/ highest possible level.

运行时异常允许使用检查型异常进行任何的异常处理,但要避免编码限制。这简化编码方式,更容易遵循throw early, catch late,也更方便在最外层或最高级别处理异常。

Leading Java frameworks and influences have now definitively moved away from checked exceptions. Spring, Hibernate and modern Java frameworks/ vendors use only runtime exceptions, and this convenience is a major factor in their popularity.

领先的java框架已经决定移除检查型异常。Spring、Hibernate 和现代的Java框架或供应商只使用运行期异常,便利性是主要原因。

Personalities such Josh Bloch (Java Collections framework), Rod Johnson, Anders Hejlsberg (father of C#), Gavin King and Stephen Colebourn (JodaTime) have all come out against checked exceptions.

Josh Bloch (Java集合框架),Rod Johnson,Anders Hejlsberg (C#之父),Gavin King and Stephen Colebourn (JodaTime)都反对检查型异常。

Now, in Java 8, lambdas are the fundamental step forward. These language features abstract the “flow of control” from functional operations within. As we’ve seen, this makes checked exceptions & the requirement to “declare or handle immediately” obsolete.

在Java8中,lambdas是一个进步,这些语言特征从基本操作中抽象出控制流,这使得检查型异常和“声明或者立即处理”的观念被废弃。

For developers, it is always important to pay attention to reliability & diagnose likely points of failure (contingencies) such as file open, database connection, etc. If we provide good error messages at this points, we will have created self-diagnosing software – a pinnacle of engineering achievement.

对于开发者而言,关注可能发生的故障比如文件打开,数据库连接等等是非常重要的。如果我们能提供适宜的错误信息,我们将创造自我诊断软件,这将是人生巅峰。

But we should do this with unchecked exceptions, and if we have to rethrow, should always use RuntimeException or an app-specific subclass.

但是我们需要使用到检查型异常,假如我们不得不重新抛出,应该使用运行期异常或是特定的应用程序级子类。

As Stephen Colebourn says, if your projects are still using or advocating checked exceptions, your skills are 5-10 years out date. Java has moved on.

正如Stephen Colebourn所说,假如你的项目仍然在使用或提倡检查型异常,你已经落后5-10年了,Java已经不使用了。

Checked exceptions: Java’s biggest mistake-检查型异常:Java最大的错误(翻译)的更多相关文章

  1. 检查型异常和非检查型异常——Java

    文章目录 检查型异常和非检查型异常--Java 检查型异常 非检查型异常 结语 检查型异常和非检查型异常--Java Java语言规范将派生于Error类或RuntimeExceprion类的所有异常 ...

  2. Java中Error和Exception的异同以及运行时异常(Runtime exception)与检查型异常(checked exception)的区别

    一:Error和Exception的基本概念: 首先Exception和Error都是继承于Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕 ...

  3. 检查型异常(Checked Exception)与非检查型异常(Unchecked Exception)

    这两个概念看了忘,碰着了又看,老是傻傻的分不清楚,今天把心得结合从网上搜的资料简单整理一下,希望帮自己明确区分开这两个概念,并牢牢的记住 1.检查型异常(Checked Exception) 个人理解 ...

  4. Java检查型异常和非检查型异常

    1.代码 public class ExcepTest { /** * @param args */ public static void main(String[] args) { System.e ...

  5. 夯实Java基础系列10:深入理解Java中的异常体系

    目录 为什么要使用异常 异常基本定义 异常体系 初识异常 异常和错误 异常的处理方式 "不负责任"的throws 纠结的finally throw : JRE也使用的关键字 异常调 ...

  6. javac命令出现“**.java使用了未经检查或不安全的操作”

    Collection col=new ArrayList();引发了“**.java使用了未经检查或不安全的操作”错误, 这是因为JDK1.5中引进了泛型,但是你的ArrayList却没有采用,所有会 ...

  7. Java基础学习总结(64)——Java内存管理

    本文介绍的Java虚拟机(JVM)的自动内存管理机制主要是参照<深入理解Java虚拟机>(第2版)一书中的内容,主要分为两个部分:Java内存区域和内存溢出异常.垃圾回收和内存分配策略.因 ...

  8. Java泛型(10):泛型与异常

    由于擦除的原因,将泛型运用于异常是非常受限的.catch语句不能捕获泛型类型的异常,因为在编译期和运行期都必须知道异常的确切类型.但是,类型参数可能会在一个方法的throw子句中用到.这使得你可以编写 ...

  9. 虚拟机--第二章java内存区域与内存溢出异常--(抄书)

    这是本人阅读周志明老师的<深入理解Java虚拟机>第二版抄写的,有很多省略,不适合直接阅读,需要阅读请出门左转淘宝,右转京东,支持周老师(侵权请联系删除) 第二章java内存区域与内存溢出 ...

随机推荐

  1. AtCoder AGC038 C-LCMs 题解

    题目链接:https://agc038.contest.atcoder.jp/tasks/agc038_c?lang=en 题意:给定一个数组,求这个数组中所有数对的LCM之和. 分析:网上看到了很多 ...

  2. JS高级---原型的简单的语法

    原型的简单的语法 构造函数,通过原型添加方法,以下语法,手动修改构造器的指向 实例化对象,并初始化,调用方法 <!DOCTYPE html> <html lang="en& ...

  3. Red Hat 7.4 安装laravel框架 基于xampp集成环境

    一.安装xampp 1.下载xampp安装包:xampp-linux-x64-7.1.10-0-installer.run 2.在安装包目录下运行命令: ./xampp-linux-x64-7.1.1 ...

  4. python自动更新升级失败解决方案

    1,使用python -m pip install --upgrade pip升级失败 2,使用python -m pip install -U --force-reinstall pip依然失败 3 ...

  5. Vue——项目中接口返回值为函数回调,回调函数定义方法(Vue的方法给原生调用)

    在接口调用中,有时会返回给我们一个函数回调,来自动执行我们在前端定义好的某个函数(多出现于通过回调的方式传递某个数值).在原生项目中,我们只要提供一下这个方法就好了,通过函数回调会自动执行.问题就出现 ...

  6. Android9 http网络请求的问题

    Google表示,为保证用户数据和设备的安全,针对下一代 Android 系统(Android P) 的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的 ...

  7. git 工具常见命令

    1.git是什么 git是分布式版本管理工具,一台电脑既可以是客户端,也可以是服务端.工作过程中可以断开网络. git中的三个概念: 1.版本库:在初始化git版本库之后会生成一个隐藏的文件, .gi ...

  8. 利用 systemd 实现 Clash 开机自启

    利用 systemd 实现 Clash 开机自启 首先准备 Clash 的服务脚本,并保存为/etc/systemd/system/clash.service.内容如下: [Unit] Descrip ...

  9. Web Storage API:localStorage 和 SessionStorage

    Web Storage API 提供了存储机制,通过该机制,浏览器可以安全地存储键值对,比使用 cookie 更加直观. 参考:https://developer.mozilla.org/zh-CN/ ...

  10. 《Web安全攻防 渗透测试实战指南 》 学习笔记 (三)

    Web安全攻防 渗透测试实战指南   学习笔记 (三) burp suite详解                                                 是一款集成化渗透测试工 ...