原文地址: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. 每天进步一点点------Altium Designer集成库简介及创建

    一.集成库概述    Altium Designer 采用了集成库的概念.在集成库中的元件不仅具有原理图中代表元件的符号,还集成了相应的功能模块.如Foot Print 封装,电路仿真模块,信号完整性 ...

  2. dbGet net trace instant pin

    proc rn { net_name } {puts " "puts "Net name : $net_name : "set name_rule [dbget ...

  3. python进阶(十七)正则&json(上)

    1. 一个列表中所有的数字都是重复2次,但是有一个数字只重复了一次. 请找出重复一次的数字,不可以使用内置函数. [2,2,1,1,0,4,3,4,3] 方法1:通过字典计数,找到value等于1的k ...

  4. Python - 用python实现split函数

    # pattern支持字符或者字符串 def my_split(string, pattern): ret = [] len_pattern = len(pattern) while True: in ...

  5. PTA的Python练习题(十五)

    第4章-12 求满足条件的斐波那契数 a=eval(input()) b=c=1 d=1 for i in range(a): c=b b=d d=b+c if d>a: print('{}'. ...

  6. 1.1、webrtc的历史和现状

    1.1.webrtc的历史和现状 本书目录 温馨提示:本书的内容,将按照顺序一一展开,上篇文章阐述本书的诞生的原因,推荐阅读方式等. 如果你还没有阅读上一篇文章(必读前言—— 作者的独白),我建议返回 ...

  7. shell中遍历数组的几种方式

    #!/bin/bash arr=( '你好') length=${#arr} echo "长度为:$length" # for 遍历 for item in ${arr[*]} d ...

  8. Python socket day2

    接收数据 需要一个端口  (端口大于1024  1024一下的端口为特殊端口)  (当同一个端口同一时间只能被一个使用) 创建一个套接字  s = socket.socket(AF_INET,SOCK ...

  9. 【C语言】创建一个函数,并调用比较两个数的大小

    #include <stdio.h> int max(int x,int y) { if(x>=y) return x; else return y; } main() { int ...

  10. IoT生态不完善、与智能电视区别不大,荣耀智慧屏概念大于实际

    编辑 | 于斌 出品 | 于见(mpyujian) 前两天,华为荣耀略显"低调"地在北京召开了一场小型的媒体沟通会.在这场沟通会上,荣耀却颇为"重磅"地推出了坊 ...