Java 8很棒。 期。 但是……在我们有机会玩耍并玩弄它之后,就该退出了,避免吃盐。 所有的好东西都是有代价的,在这篇文章中,我将分享Java 8的主要痛点。请确保在升级和放弃7之前您已经意识到了这些痛点。

1.并行流实际上会使您减速

Java 8将并行性作为最令人期待的新功能之一带来了希望。 .parallelStream()方法在集合和流上实现此功能。 它将它们分解为子问题,然后在单独的线程上运行以进行处理,这些子问题可以进入不同的核心,然后在完成后组合在一起。 这一切都是在使用fork / join框架进行的 。 听起来不错,它必须加快多核环境中大型数据集的操作,对吗?

不,如果使用不正确,它实际上会使您的代码运行缓慢。 慢上大约15% 这个基准,我们跑了,但它可能会更糟糕。 假设我们已经在运行多个线程,并且在其中一些线程中使用了.parallelStream(),从而向池中添加了越来越多的线程。 这很容易变成我们的核心无法处理的事情,并且由于增加了上下文切换而减慢了一切。

基准测试速度较慢,将集合分为不同的组(素数/非素数):

Map<Boolean, List<Integer>> groupByPrimary = numbers
.parallelStream().collect(Collectors.groupingBy(s -> Utility.isPrime(s)));

同样,由于其他原因,速度也会变慢。 考虑到这一点,假设我们有多个任务要完成,由于某种原因,其中一个要比其他任务花费更长的时间。 使用.parallelStream()分解它实际上可能会延迟完成较快的任务以及整个过程。 请查看Lukas Krecan的这篇文章,以获取更多示例和代码示例。

诊断:并行性及其所有优点也带来了其他类型的问题需要考虑。 当已经在多线程环境中执行操作时,请记住这一点,并使自己熟悉幕后发生的事情。

2. Lambda表达式的反面

Lambdas。 哦,lambdas。 如果没有您,我们几乎可以做所有我们已经可以做的事情,但是您却增加了很多宽限期,并且摆脱了样板代码,因此很容易坠入爱河。 假设我是早上起来 ,想遍历一队世界杯球队并确定他们的身长(有趣的事实:总数达到254):

List lengths = new ArrayList();for (String countries : Arrays.asList(args)) {lengths.add(check(country));
}

现在,让我们通过一个很好的lambda来实现功能:

Stream lengths = countries.stream().map(countries -> check(country));

宝贝! 太好了 尽管……虽然通常被视为是一件好事,但在Java中添加诸如lambdas之类的新元素会使它进一步偏离其原始规范。 字节码完全为OO,并且在游戏中带有lambda,因此实际代码与运行时之间的距离会增大。 在Tal Weiss的这篇文章中阅读有关lambda表达的黑暗面的更多信息。

最重要的是,这一切都意味着您正在编写的内容和正在调试的内容是两件事。 堆栈跟踪越来越大,使调试代码变得更加困难。

简单的操作(例如,向列表中添加一个空字符串)将使此简短的堆栈跟踪成为可能:

at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.main(LmbdaMain.java:34)

变成这个:

at LmbdaMain.check(LmbdaMain.java:19)
at LmbdaMain.lambda$0(LmbdaMain.java:37)
at LmbdaMain$$Lambda$1/821270929.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.LongPipeline.reduce(LongPipeline.java:438)
at java.util.stream.LongPipeline.sum(LongPipeline.java:396)
at java.util.stream.ReferencePipeline.count(ReferencePipeline.java:526)
at LmbdaMain.main(LmbdaMain.java:39)

Lambda引发的另一个问题与重载有关:由于Lambda参数在使用它们调用方法时必须转换为某种东西,并且它们可以转换为多种类型,因此在某些情况下可能会导致模棱两可的调用。 Lukas Eder 在此处通过代码示例对此进行了解释。

诊断:仅需注意这一点,痕迹可能会不时带来痛苦,但不会使我们远离它们。

3.默认方法会分散注意力

默认方法启用接口本身中功能的默认实现。 这无疑是Java 8带来的最酷的新功能之一,但是它在某种程度上干扰了我们过去的工作方式。 那么为什么要引入这个呢? 那与它无关吗?

默认方法背后的主要动机是,如果在某个时候我们需要向现有接口添加方法,则无需重写实现就可以做到这一点。 与旧版本兼容。 例如,从Oracle Java教程中获得以下这段代码,它们在其中添加了指定时区的功能:

public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {return ZoneId.of(zoneString);
} catch (DateTimeException e) {System.err.println("Invalid time zone: " + zoneString +"; using default time zone instead.");return ZoneId.systemDefault();}
}default public ZonedDateTime getZonedDateTime(String zoneString) {return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));}
}

就是这样,问题解决了。 还是? 默认方法混淆了接口和实现的分离。 在错误的手中,仿佛类型层次结构不会自己纠结,现在我们需要驯服这种新生物。 在Oleg Shelajev在RebelLabs上的帖子中了解有关此内容的更多信息。

诊断:当您拿着锤子时,所有东西都看起来像钉子,请牢记坚持其原始用例,当重构引入新的抽象类时,现有接口的演变毫无意义。

继续进行一些遗失,仍在我们身边或尚未完全存在的事情:

4.为什么您是

Jigsaw项目的目标是使Java模块化并将JRE分解为可互操作的组件。 首先,其背后的动机来自对更好,更快,更强大的 Java嵌入式的渴望。 我试图避免提及“物联网”,但是我在那说了。 减小JAR大小,提高性能和提高安全性是这个雄心勃勃的项目所具有的更多希望。

那在哪呢 甲骨文首席Java架构师Mark Reinhold表示,拼图刚进入了第二阶段 ,已经通过了探索阶段,现在正在将其转换为生产质量设计和实现。 该项目最初计划在Java 8中完成,然后推迟到Java 9,有望成为其旗舰新功能之一。

诊断:如果这是您要等待的主要内容,则Java 9将于2016年推出。与此同时,仔细研究一下,甚至可能会涉及到Jigsaw-dev邮件列表。

5.仍然存在的问题

检查异常

没有人喜欢样板代码,这就是lambda如此受欢迎的原因之一。 考虑样板异常,无论逻辑上是否需要捕获或与检查异常相关 ,您仍然需要捕获它。 即使这是永远不会发生的事情,例如永远不会触发的异常:

try {httpConn.setRequestMethod("GET");
} catch (ProtocolException pe) { /* Why don’t you call me anymore? */ }

原语

它们仍然在这里,正确使用它们很痛苦 。 将Java与纯粹的面向对象的语言区别开来的一件事是,批评说Java的删除对其性能没有重大影响 。 只是说,所有新的JVM语言都没有它们。

操作员超载

Java的父亲James Gosling在一次采访中曾说过:“我忽略了运算符重载,这是一个非常个人的选择,因为我看到太多的人在C ++中滥用它”。 有点道理,但是对此有很多不同意见。 其他JVM语言确实提供了此功能,但另一方面,它可能会导致代码如下所示:

javascriptEntryPoints <<= (sourceDirectory in Compile)(base =>((base / "assets" ** "*.js") --- (base / "assets" ** "_*")).get
)

来自Scala Play框架的实际代码行,嗯,我现在有点头晕。

诊断:这些是否是真正的问题? 我们都有自己的怪癖,这些都是Java的怪癖。 在将来的版本中可能会发生意外的情况,并且会有所变化,但是向后兼容性以及其他方面的兼容性使它们始终与我们保持联系。

6.函数式编程–还不完全

尽管以前很尴尬,但以前使用Java可以进行函数式编程。 Java 8借助lambda对此进行了改进。 这是最受欢迎的,但没有以前描述的那么大。 绝对比Java 7更优雅,但仍需要向后弯曲才能真正发挥作用。

关于此问题的最激烈的评论之一来自Pierre-yves Saumont,他在一系列文章中仔细研究了函数式编程范例与在Java中实现它们之间的区别。

那么Java还是Scala? Java中采用功能更强大的现代范例对Scala表示认可,因为Scala一直在使用lambda。 Lambda确实引起了很大的反响,但是还有很多特性,例如特征,懒惰的评估和不可变的特性等,它们会产生很大的影响。

诊断:不要被lambda分散注意力,在Java 8中函数式编程仍然很麻烦。

翻译自: https://www.javacodegeeks.com/2014/07/6-reasons-not-to-switch-to-java-8-just-yet.html

仍不切换到Java 8的6个理由相关推荐

  1. java7和java8切换_仍不切换到Java 8的6个理由

    java7和java8切换 Java 8很棒. 期. 但是--在我们有机会玩耍并玩弄它之后,就该退出了,避免吃盐. 所有的好东西都是有代价的,在这篇文章中,我将分享Java 8的主要痛点.请确保在升级 ...

  2. JetBrains 宣布:IntelliJ 平台彻底停用 Log4j 组件,建议切换至 java.util.logging

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:segmentfault.com/a/1190000041400202 近日,JetBrains 官方博客发文宣布:Intel ...

  3. 从Python切换到Java是个好主意吗?

    将Python作为第一门编程语言的想法具有合理的背景. 首先,Python的语法简短明了,并且工作的对象和变量的基础模型完全一致. 这意味着您无需费力即可编写"真实的"且功能强大的 ...

  4. 银行不敢切换容灾系统的六个理由

    银行不敢切换容灾系统的六个理由 导读]记者采访了<重要信息系统灾难恢复指南>起草人之一.GDS万国数据服务有限公司首席灾备专家汪琪,著名的信息安全专家.北京大学软件与微电子学院院长陈钟,北 ...

  5. SpringBoot中英文切换/国际化——java后端怎么用预置文本的内容替换web网页内容(Resource Bundle)

    文章目录 创建预置文件文本内容 Thymeleaf修改前端使其获得预置文本内容 html页面设置跳转标签和传值 创建一个MyLocaleResolver配置文件 在MvcConfiguration中注 ...

  6. java单击切换div_[Java教程]点击同一按钮实现div的隐藏与现实切换

    [Java教程]点击同一按钮实现div的隐藏与现实切换 0 2016-01-16 21:00:12 点击同一按钮实现div的隐藏与现实切换: 在很多应用中,都有这样的功能,点击同一个按钮可以实现div ...

  7. java swing 图片切换_在一个界面中要实现图片切换,用java要肿么实现??

    通常可以设置某个固定的切换时间,之后显示固定的或者是随机的显示某张图片,举例: import java.awt.*; import java.awt.event.*; import javax.swi ...

  8. java怎么实现tab切换_[Java教程]用javascript实现tab切换

    [Java教程]用javascript实现tab切换 0 2016-09-12 14:00:10 html代码: 111111 222222 333333 css代码:.active{ backgro ...

  9. 网页上的双语切换(java+jsp/html)

    很多网站或手机端网页都可以做双语切换,以下是利用配置文件实现双语切换的讲解(我使用spring mvc+jsp) 我使用的切换是利用了java服务器的session来实现的(只有三个步骤,第三个步骤里 ...

最新文章

  1. mysql trim前后空格_MySQL清除字符串首尾空格函数trim
  2. 【IPFS + 区块链 系列】 入门篇 - IPFS+IPNS+个人博客搭建
  3. flink sql planner到底是干嘛用的
  4. 什么叫做罗列式_极简罗列法怎么写作文
  5. osm数据下载 python_GIS Experience (十):OSM数据获取
  6. PHP以xml形式获取POST数据
  7. Net-DataGridView
  8. Linux内核深入理解系统调用(1):初始化-入口-处理-退出
  9. C#串口通信工作笔记0001---上位机开发_嵌入式_串口助手_收发数据开发
  10. linux 嵌入式 人工智能,嵌入式人工智能有哪些相关技术
  11. Python的for循环显示每个元素的下标
  12. 剑指offer面试题[54]-表示数值的字符串
  13. js实现敏感词过滤算法
  14. 微信小程序实现图片上传
  15. python商城管理系统_【程序源代码】全端商城管理系统(后台+小程序)
  16. Deepin安装应用
  17. {typedir} {style} {tid} {aid} 分别是什么意思?
  18. asp.net mvc 网站生成二维码
  19. python循环5次_python基础-循环语句(5)
  20. git修改已提交commit的Author信息

热门文章

  1. python3 爬虫例子_如何让你写的爬虫速度像坐火箭一样快【并发请求】
  2. 钟 docker讲解
  3. java异常 字节码,Java字节码角度分析异常处理
  4. es6 dsl与sql对比
  5. 异常java.lang.Thread.dumpStack(Unknown Source)
  6. leetcode初级算法3.存在重复元素
  7. HDU2059(DP)
  8. 使用poi统计工作职责
  9. jetty java_Jetty,Java和OAuth入门
  10. jakarta ee_MicroProfile在Jakarta EE时代的作用