JDK7中的新功能和值得注意的功能

JDK7的最新预览版是Oracle在Java未来的不确定性中发出的第一个公开消息。 JDK7 最初面向2008-2009,并承诺提供一些出色的新语言功能,其中最著名的是lambda支持,新集合支持和无符号文字。 预览发布晚了大约24个月,其中仅包含了一些新的语言功能,但是鉴于目前的艰难道路,这可能是可以预期的。 在本文中,我们将仔细研究其中的一些新功能,并讨论它们实际上可能有用的程度,以及扩展到Java在人满为患的语言市场中的地位。

Java已经开始显示它的年龄,现在已经有16年了,还没有跟上现代开发人员的步伐。 JVM已经证明自己是一个重要的执行平台,但该语言本身已经开始过时。 随着当前函数式编程的趋势以及以JVM为目标的语言(例如Scala,Java)的兴起,该语言已处于与Java平台竞争的地位。 JDK7的新语言功能是否可以增强该语言的地位,还是为时已晚? 新的和值得注意的语言功能的摘要包括:

•关于通用对象创建的类型推断

•资源尝试语句

•在单个catch块中捕获多个异常

通用对象创建和构造函数参数的类型推断

至少在实例化新的通用对象时可以推断类型时,此新功能使该语言的通用性更为简洁。 例如,

私有Map <Size,List <Shoe >> stock = new HashMap <Size,List <Shoe >>();

可以简化为:

私有Map <Size,List <Shoe >> stock = new HashMap <>();

从声明中可以推断出钻石操作员。 它与完全遗漏泛型有细微的差别,这会将您的类型减少为Object。 一般推理规则适用。 因此,例如,可以使用方法的返回类型来推断类型,如下例所示。

JDK7中的新功能和值得注意的功能

事情没有比这更好的了。 实际上,他们做到了。 一点点 构造函数泛型通常一直很有趣,并且并没有真正改变,尽管有了JDK7,您可以做更多的事情。 例如,

JDK7中的新功能和值得注意的功能

这些示例与Oracle提供的示例相同 (或多或少),它们都仅与JDK7一起使用,并显示与Diamond运算符组合为类通用(X)的Integer类型。 第二个示例显示了新的语法,用于显式设置泛型方法的类型,以进行一些其他的编译时检查。 具体来说,如果您尝试疯狂的事情,例如:

JDK7中的新功能和值得注意的功能

您会看到这样的友好编译错误

JDK7中的新功能和值得注意的功能

有趣的是, Oracle自己的示例实际上并未针对JDK7预览版进行编译。 在官方文档中,它们显示以下内容

JDK7中的新功能和值得注意的功能

不会为我编译,因为无法为MyClass <>错误推断类型参数。 这意味着您不能对通用构造函数参数使用具有明确类型说明的菱形运算符。 这听起来太夸张了,我敢肯定这是一个疏忽,后续更新将与Oracle文档保持一致。 他们似乎还以roguè为例将错字误入了官方文档;

MyClass <Integer> myObject =新的<String`> MyClass <>(“”)

删除它,一切都会编译。 离开它,疲惫不堪。 麻烦的是,网络上的所有示例几乎都基于其文档,因此请小心谨慎。 为了减少我们所看到的视觉混乱,此功能一点都不令人印象深刻。 实际上,诸如IntelliJ IDEA之类的IDE已经进行了一段时间。 如果您在IDEA中查看上面的第一个示例,它将自动使用代码折叠来隐藏重复并显示类似以下内容。

私有Map <Size,List <Shoe >> stock = new HashMap <〜>();

结合击中和遗失文档,Oracle的这一新语言功能无疑令人难以置信。

try-with-resources语句和AutoCloseable


Java冗长的另一个错误一直是try-catch-finally语法。 新的语言功能try-with-resources语句使您可以结合自动关闭的资源来压缩它。 在这里,您可以在try语句的括号内(只要对象实现AutoCloseable接口)“打开”资源,而不是熟悉的try-finally最后关闭资源的方法,而Java将负责close调用。 例如, Oracle的文档显示了如何

JDK7中的新功能和值得注意的功能

变成

JDK7中的新功能和值得注意的功能

这种减少语法的方法很有趣,因为它大大减少了尝试块的典型噪声。 一个扩展且太熟悉的示例可能是常见的try-try-catch-donothing块,例如以下代码。

JDK7中的新功能和值得注意的功能

可以减少到

JDK7中的新功能和值得注意的功能

在这里,可自动关闭的资源已经处理了关闭流的调用,并且在实现中也为我们处理了null检查。 不利的一面是,FileInputStream中close的实现向捕获列表添加了IOException(更准确地说,扩展了AutoCloseable并由FileInputStream实现的Closeable接口添加了异常)。 总体而言,尽管有例外,但这应该有助于整理这种资源的使用情况,以便对此大加赞赏。 但是,对于我来说还不清楚,为什么Oracle选择了拼写错误的接口名称。

JDK7中的新功能和值得注意的功能

还有一些额外的细节,在使用try-with-resources时可能会很麻烦,并且这是抑制的异常。 可以抑制在close方法内引发的异常,而赞成在try语句的块内引发的异常。 让我们仔细看一下。

JDK7中的新功能和值得注意的功能

上面的示例演示了close方法中引发的异常,但该异常被抑制了,在这种情况下,默认异常处理程序捕获的实际异常将是RuntimeException。 例如,

JDK7中的新功能和值得注意的功能

如果我们根据上面的反编译版本将某些内容放在一起,则可以看到幕后发生的事情。

JDK7中的新功能和值得注意的功能

JavaDoc告诉我们,在这种情况下,在逻辑上抛出了两个异常,但是由于控制流只能在发生一个异常的情况下继续,因此另一个异常被抑制了。 受抑制的异常是JDK7中的新增功能,可以通过“ getter”方法以类似的方式检索原因。 我偶尔会看到这引起奇怪的问题,因为我想它将成为另一个鲜为人知的警告,直到为时已晚,您才需要意识到这一点。 公平地讲,编写自己的AutoCloseable实现比使用Oracle改进的类可能更成问题。

也许更多的是将使用AutoCloseable作为协作者的东西放在一起进行测试。 以前,如果某些东西可以与InputStream一起使用,我们通常会将其(接口)直接注入到要测试的类中并拥有它。 当我们在try-with-resources语句中“更新”协作者时,我们无法做到这一点,因此我们*通过工厂。 这并不是一个很大的问题,但是它可能导致另一个间接合作者,您可能会争论不清。 例如,以下内容不会编译。

JDK7中的新功能和值得注意的功能

因此,我们*使用工厂。

JDK7中的新功能和值得注意的功能

这反过来意味着一个典型的测试(在我们的案例中使用jmock)更加冗长。 我将由您来决定这是否可能成为问题。

JDK7中的新功能和值得注意的功能

Kabutz博士将此新功能与一种自动解锁最近新闻信件中的锁定资源的方式结合在一起。 在这里,Java Champion实现了java.util.concurrent.Lock的基本解锁。

JDK7中的新功能和值得注意的功能

客户打电话给像

JDK7中的新功能和值得注意的功能

尽管这是新功能的有趣用法,但是开发人员已经通过包装接口的一些匿名实例或使用这种样板重复来装饰类,从而解决了这种冗长的问题。 我为tempus-fugit微库编写的示例如下所示:

JDK7中的新功能和值得注意的功能

在熟悉的finally块中找到“关闭”调用。 这是迈向类似lambda的方法的一个很好的例子,在该方法中,客户将调用如下的匿名实现(将静态导入用于更多语法糖)。

JDK7中的新功能和值得注意的功能

我之所以提到这种替代方法,是为了反思Oracle推迟采取的更重要的支持lambda的举措。 tempus-fugit示例很冗长,因为Java很冗长,但由于语言支持lambda,开发人员可以*地以简洁的方式解决自己的问题。 tempus-fugit示例在Java的约束范围内工作,试图消除噪音,但是通过引入适当的lambda,我们就不需要这样做了。 引入try-withresources是对我们通常所忍受的噪声的一种响应,但它只针对非常具体的情况。 如果相反,我们看到了lambda支持,那么对这样的事情就不会有这样的需求。 我们已经将所有方式编码出来了。

捕获多个异常

这项新功能使您可以使用管道来分隔多个异常类型来捕获多个异常。 它删除了您经常会捕获的多个异常并以相同方式对其进行处理的重复代码。 例如,

JDK7中的新功能和值得注意的功能

对于Java的一般用法,这似乎是另一种解决方法。 如果您在一段代码周围有很多页面和catch语句,则可能是想告诉您一些信息。 在Java中,异常处理经常引起争议。 强制检查异常通常会导致过度使用“捕捉并抛出”反模式,并且需要采取认真考虑的方法来避免混乱。

依靠新语法的一些替代方法很可能会导致一个更好的系统,包括分解问题,识别和分离角色和职责以及作为副产品隔离异常生成代码。 您也可以尝试使用类似lambda的匿名接口实现或香草装饰,将异常处理代码推到一边(通常在此处最好记录或包装)。

尽管确定系统的真正边界,但可能比机制更重要。 您实际上与系统参与者交互的那些地方,例如UI,框架或只是系统的体系结构“层”。 一旦发现这些异常,就可以采取措施在适当的地方处理异常,并回答何时重新抛出异常的问题。 对此的逻辑扩展是将异常视为RuntimeException的子类,并且仅在您的边界上捕获和处理它们。 完全避免检查异常可以极大地减少混乱,但是抛出运行时异常将使开发人员承担高度责任,这与典型的“防御性代码”开发文化不符。

鉴于上面来自Oracle的示例,我怀疑此新功能只会使难看的代码陷入困境。 似乎说“可以用相同的方式处理大量异常。 实际上,我们会让您更轻松”。 对于Java世界来说,如果您实际上应该做某事,永远不会发生警告,只是概述如何做。 上面的示例(顺便说一下,Oracle的示例)随后重新抛出日志的事实本身就是一种味道,世界各地的开发人员很可能会复制该事实(毕竟它具有Oracle的正式认可印章)。 也许我太苛刻了,但是我不喜欢这个。

JDK7版本中还增加了许多API,此处未提及太多。 但是,一些值得注意的地方包括一个新的Objects类,该类提供了帮助实现null安全性的辅助方法和一个简单的deep equals方法。 在广受欢迎的并发包中,有一个新的双端队列(Deque)实现和一个基于链表的传输队列。 总而言之,我不认为普通的开发人员会为这些次要的功能而大声疾呼,也不会喜欢这些功能。

我当然已经将重点放在语言功能上,而JDK7发行版将不仅仅是语言功能,包括对JDBC,NIO的更新,以及用于在Solaris上通过InfiniBand架构进行流传输的新Sockets Direct Protocol。 我还省略了其他一些新语言功能的详细信息。 我们可以期待在抛出异常方面有更多的特殊性,更好地支持在JVM上运行的动态类型的语言(通过新的invokedynamically字节代码指令),二进制文字(0B10101010),数字文字下划线和在switch语句中使用字符串的能力。

结论

最近的趋势和新的以JVM为目标的语言的出现,意味着Java已经开始显得有些陈旧,有些long不休。 除其他外,Scala提供了一种更轻松,更优雅的方式来锻炼我们的手艺。 JDK7的新语言功能显然旨在解决社区对Java的不满,但距离修复Java逐渐衰落的声誉还远远不够。 就像过去两个月以来,我们一直在为JDK7进行拉幅拉钩一样。

由于Java平台近五年没有主要版本发布,因此 Oracle不得不浪费很多时间来弥补。 为了满足开发人员社区的需求,出现了更新,更优雅,更简洁的语言,并且大多数语言都在JVM上运行。 作为一个平台,Java感到安全可靠,是一个温暖的地方。它是一个经过验证的,经过强化的平台,新的参与者很乐意在此前提下建立自己的未来。 但是,要想与一种语言竞争,甲骨文就必须像在2004年发布Java 5时那样向前倾斜Java的语言功能,而JDK7版本不是。 太多的土地已经丢失,Java与现代开发人员失去联系。 Lambda支持或可更改的泛型类型可能有助于保持新鲜感,但我想知道它们是否会到来,如果可以,那么到那时我们是否会继续前进。 平台本身也应该期待。 缺少对无限堆栈或原子多地址更新(支持STM)的JVM的支持,意味着该平台也无法坐拥桂冠。


翻译自: https://jaxenter.com/new-and-noteworthy-in-jdk7-103549.html