Java的坏功能是什么

总览

当您第一次学习开发时,您会看到关于不同功能的过分笼统的陈述,对于设计,性能,清晰度,可维护性来说,都是不好的,感觉就像是黑客,或者他们只是不喜欢。

这可能会得到现实世界经验的支持,在实际经验中,删除功能的使用可以改善代码。 有时这是因为开发人员不知道如何正确使用该功能,或者该功能固有地容易出错(取决于您是否喜欢它)

当时尚或您的团队改变并且此功能变得很好甚至是首选方法时,这令人感到不安。

在这篇文章中,我研究了人们喜欢讨厌的某些功能,以及为什么我认为使用正确的功能,它们应该成为有益的力量。 功能不像是/否,好/坏,就像许多人相信的那样。

检查异常

对于开发人员不喜欢考虑错误处理的程度,我经常感到惊讶。 新开发人员甚至不喜欢阅读错误消息。 这是艰苦的工作,他们抱怨应用程序崩溃,“它不起作用”。 他们不知道为什么当错误消息和堆栈转储经常告诉他们如果他们只能看到线索的确切原因时,会引发异常。 当我出于跟踪目的而写出堆栈跟踪信息时,许多人只会在没有错误的情况下看到日志形状像崩溃一样。 读取错误消息是一种技巧,起初它可能会让人不知所措。

同样,也经常避免以有用的方式处理异常。 我不知道该异常该怎么办,我宁愿记录该异常并假装它没有发生,或者只是炸掉,然后让操作人员或GUI用户处理错误的能力最弱。

结果,许多经验丰富的开发人员都讨厌检查异常。 但是,我听到的越多,我越高兴Java检查了异常,因为我坚信Java确实会发现忽略异常非常容易,并且只要不被它们烦恼就让应用程序死亡。

检查异常当然可以被过度使用。 问题应该是抛出检查异常时。 我是否想通过迫使他们对错误处理进行一点思考来惹恼开发人员调用代码? 如果答案是肯定的,则抛出一个已检查的异常。

恕我直言,这是lambda设计的失败,因为它无法透明地处理检查的异常。 例如,作为自然的代码块,可以抛出未处理的异常,就像处理未经检查的异常和错误一样。 但是,考虑到lambda和函数式编程的历史,它们根本不喜欢副作用,更不用说快捷错误处理了,这也就不足为奇了。

通过重新抛出已检查的异常,就好像它是未检查的异常一样,您可以绕过lambda的限制。 之所以可以这样做是因为JVM没有检查异常的概念,它像泛型一样是编译时检查。 我的首选方法是使用Unsafe.rethrowException,但还有3种其他方式可以做到这一点。 尽管Thread.currentThread()。stop(e)总是很安全,但它不再在Java 8中工作。

Thread.currentThread()。stop(e)不安全吗?

当Thread.stop(Throwable)方法可能导致另一个线程在代码的随机部分触发异常时,它是不安全的。 这可能是一部分代码中未检查到的异常,也可能是抛出该异常的原因,该异常捕获在线程的某些部分,但其他部分则使您不知道它会做什么。

但是,它不安全的主要原因是,它可能会使原子操作处于不一致状态的代码锁定部分的同步状态,从而以微妙且不可测试的方式破坏内存。
更令人困惑的是,Throwable的堆栈跟踪与实际引发异常的线程的堆栈跟踪不匹配。

但是Thread.currentThread()。stop(e)呢? 这触发当前线程在当前行上引发异常。 这并不比仅使用throw异常执行正在执行的编译器无法检查的操作更糟。 问题在于,编译器并不总是知道您在做什么,以及它是否真的安全。 对于泛型,这被归类为“未经检查的强制转换”,这是一个警告,您可以通过注释禁用它。 Java不能很好地支持带有检查异常的同类操作,因此您最终会使用hack,或者更糟糕的是将真正的检查异常隐藏为运行时异常,这意味着调用者无法正确处理它。

使用

对我来说,这是一个新的“规则”。 我知道它来自哪里,但是该规则比应该应用的地方有更多的例外。 让我们首先考虑所有可以使用重载static的上下文。

  1. 静态可变字段
  2. 静态不可变字段(指向不变的对象的最终原始或最终字段)
  3. 静态方法。
  4. 静态类(没有隐式引用外部实例)
  5. 静态初始化程序块。

我同意使用静态可变字段可能是新手错误,或者是有可能避免的东西。 如果您看到静态字段在构造函数中被更改,则几乎可以肯定是一个错误(即使没有,我也会避免),我相信这是避免所有静态语句的原因。

但是,在所有其他情况下,使用static不仅性能更高,而且更清楚。 它表明此字段对于每个实例都不同,或者该方法或类并不隐含地依赖于实例。

简而言之,static是好的,可变的static字段是例外,而不是规则。

Singletons不好吗?

单例的问题来自两个方向。 它们是有效的全局可变状态,使其难以维护或封装(例如在单元测试中),并且支持自动装配。 也就是说,任何组件都可以访问它,从而使您的依赖项变得不清楚并且难以管理。 由于这些原因,一些开发人员讨厌它们。

但是,遵循良好的依赖关系注入是一种应该应用于所有组件(无论是否单例)的方法,并且应该避免通过单例避免全局可变状态。

如果排除全局状态和自连接组件,则剩下的Singleton是不可变的,并通过依赖项注入传递,在这种情况下,它们可以正常工作。 我用于实现策略的一种常见模式是将枚举与一个实现接口的实例一起使用。

enum MyComparator implements Comparator {INSTANCE;public int compare(MyObject o1, MyObject o2) {// something a bit too complicated to put in a lambda}}

该实例可以通过依赖项注入作为Comparator的实现传递,并且没有可变状态,可以在线程和单元测试之间安全地使用。

我可以让一个库或框架为我做一件非常简单的事情吗?

库和框架可以为您节省大量时间和精力,使您自己的代码执行在其他地方已经可以使用的操作。

即使您想编写自己的代码,我也强烈建议您了解现有库和框架的功能,以便您可以从中学习。 自己编写它不是避免理解任何现有解决方案的捷径。 一位记者曾经绝望地写到一位有抱负的记者。 不喜欢读书,只喜欢写作。 在软件开发中也是如此。

但是,我已经看到(在Stackoverflow上)开发人员竭尽全力避免将自己的代码用于琐碎的示例。 他们觉得如果使用库,它必须比他们编写的任何东西都要好。 问题在于它是假定的。 添加库并不会增加复杂性,您对库有很好的了解,而且您将不需要学习编写可以信任的代码。

一些开发人员使用框架来帮助学习实际的方法论。 实际上,开发人员通常会使用纯Java进行依赖注入的框架,但是他们要么不信任自己,要么不信任自己的团队来这样做。

在高性能空间中,代码越简单,应用程序所做的工作就越少,使用更少的活动部件进行维护就越容易,并且运行速度也就越快。 您需要使用最少的库和框架,这些库和框架应相当容易理解,以便使您的系统发挥最佳性能。

用双钱赚钱不好吗?

在不考虑舍入的情况下使用分数将为您带来意想不到的结果。 从正面看,对于双精度数,通常显然是错误的,例如10.99999999999998,而不是11。

有些人认为BigDecimal是解决方案。 但是,问题在于BigDecimal拥有自己的陷阱,很难进行验证/读取/写入,但如果没有,最糟糕的情况是看起来正确。 举个例子:

double d = 1.0 / 3 * 3 + 0.01;BigDecimal bd1 = BigDecimal.valueOf(1.0).divide(BigDecimal.valueOf(3), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(3)).add(BigDecimal.valueOf(0.01)).setScale(2, BigDecimal.ROUND_HALF_UP);BigDecimal bd2 = BigDecimal.valueOf(1.0).divide(BigDecimal.valueOf(3), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(3).add(BigDecimal.valueOf(0.01))).setScale(2, BigDecimal.ROUND_HALF_UP);System.out.println("d: " + d);System.out.println("bd1: " + bd1);System.out.println("bd2: " + bd2);

这将产生三个不同的结果。 通过观察,哪一个产生正确的结果? 您能说出bd1和bd2之间的区别吗?

打印:

d: 1.01
bd1: 1.00
bd2: 0.99

您可以从输出中看到哪个错误吗? 实际上答案应该是1.01。

BigDecimal的另一个难题是equals和compareTo的行为不同。 当compareTo()返回0时,equals()可以为false。即,在BigDecimal 1.0中,等于1.00时为false,因为比例不同。

BigDecimal的问题在于,您获得的代码通常更难于理解,并且会产生看起来不正确的错误结果。 BigDecimal的速度明显较慢,并且会产生大量垃圾。 (这在Java 8的每个版本中都在改进)在某些情况下,BigDecimal是最好的解决方案,但并非如某些人所反对那样是给定的。

如果BigDecimal不是一个很好的选择,还有其他吗? int和long通常以固定的精度使用,例如,整数而不是分数。 这有一些挑战,您必须记住小数位在哪里。 如果Java支持值类型,将它们用作金钱包装器并为您提供更多安全性可能是有意义的,但是处理整数原语的控制,明确性和性能。

使用

对于NullPointerException Java的开发人员来说,重复获得NullPointerException是一种消耗体力的体验。 我真的必须为Java中数组中的每个对象,每个元素创建一个新实例吗? 其他语言则不需要这样做,因为通常是通过嵌入式数据结构来完成的。 (Java正在考虑的事物)

即使是经验丰富的Java开发人员也难以处理null值,并将该语言中的null视为一个大错误。 恕我直言,问题是替代品往往差得多。 例如不是NPE的NULL对象,但也许应该已经初始化为其他对象。 在Java 8中,Optional是一个很好的添加,它使对非结果的处理更加清晰。 我认为这对那些与NullPointerException斗争的人很有用,因为它迫使您考虑可能根本没有结果。 这不能解决未初始化字段的问题。

我个人不喜欢它,因为它解决了一个问题,可以通过正确处理null来解决更广泛的问题,但是我认为对于许多人来说,这是一种改进。

一个常见的问题是; 我应该如何知道变量为空? 这是我心中错误的方法。 应该是,为什么要假设它不能为null? 如果您不能回答该问题,则必须假定它可以为null,并且如果不进行检查,NPE也就不会感到惊讶。

您可能会争辩说Java可以使用更多的语法糖来制作处理Elvis运算符之类的用于null清除程序的代码,但是我认为问题在于开发人员并未充分考虑null值。 例如,在打开它之前是否检查枚举变量是否为null? (我认为应该有一个case nullcase null :在switch中,但不存在或陷入default :但事实并非如此)

快速编写代码有多重要?

Java不是一种简洁的语言,并且没有IDE来为您编写一半的代码,如果您花了一整天时间编写代码,那么编写esp确实会很痛苦。

但这就是开发人员整日不做的事情吗? 实际上,他们没有。 开发人员不会花费很多时间来编写代码,他们会花费90%(对于新代码)到99%(对于遗留代码)来理解问题

你可能会说; 我整天和以后写了1000行代码,然后重新编写代码(通常使代码更短),一段时间后我修复了代码。但是,尽管您仍然想起这段代码,但是如果您只是编写最后需要的代码(或者从打印输出中完成),然后将其除以在项目上花费的总时间,从头到尾,您可能会发现实际上每天少于100行代码,每天可能少于10行。

因此,如果那段时间不是写最终产品,那您实际上在做什么? 据了解,最终用户需要什么,以及实施该解决方案需要什么。

曾经有人告诉我; 如果您在错误的位置钻Kong,则无论钻Kong多快,多大,有多深或有多少Kong都无所谓。

结论

我听到了从初学者到杰出开发人员的观点,声称您不应该/我无法想象为什么/如果您使用X,您应该被解雇,应该只使用Y。我发现这样的陈述很少100%准确。 通常,要么存在边际情况,有时在非常常见的情况下,这种陈述具有误导性或完全不正确。

我会以怀疑的态度对待任何这样的广泛评论,而且他们常常发现一旦看到其他人的观点不一致,他们就必须限定所说的内容。

翻译自: https://www.javacodegeeks.com/2015/05/what-are-the-bad-features-of-java.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试题(2)

逻辑推理 1、你让工人为你工作7天,给工人的回报是一根金条。金条平分成相连的7段 ,你必须在每天结束时给他们一段金条,如果只许你两次把金条弄断,你如何给你 的工人付费?   2、请把一盒蛋糕切成8份,分给8…

语句 查询每个人每个科目的最高分_转行数据分析师专栏(SQL篇)-05多表查询...

数据表(4张)及数据情况:搭建数据表数据参考:空杯希望:转行数据分析师专栏(SQL篇)-01SQL入门​zhuanlan.zhihu.com一、表的加法1、先新建一个表course1(和course表数据结构一致&#…

星海中学2021高考成绩查询,广东中考时间2021

忙碌了整整一个学期,同学们最关心的当然是什么时候能好好的回家调节一下学习的节奏,一起来看看广东各个大学的寒假放假时间吧!下面是由出国留学网小编为大家整理的“2021广东各大学寒假放假时间”,仅供参考,欢迎大家阅…

JDK 8 SummaryStatistics类

JDK 8中引入的三个新类是java.util包的DoubleSummaryStatistics , IntSummaryStatistics和LongSummaryStatistics 。 这些类使计算元素总数,元素最小值,元素最大值,元素平均值以及双精度,整数或long的集合中的元素总和…

plsql 设置鼠标行执行_如何制作键盘鼠标产品质量合格证

鼠标前盘属于办公用品套装,一般会一起销售,但是也不排除分开销售,无论是哪种方式键盘鼠标在生产销售时都需要携带对应产品质量合格证,对产品进行简单的说明,更能保障消费者的权益。那么如何制作产品质量合格证呢&#…

第四章例4-2

/* 输入一批学生的成绩&#xff0c;以负数作为结束标志&#xff0c;计算平均成绩&#xff0c;并统计不及格人数 */ #include<stdio.h> int main(void) {int count,num;double grade,total;num0;total0;count0;printf("Enter grades:");scanf_s("%lf"…

Spring RESTful错误处理

这篇文章将说明在Spring中可以为RESTful Web服务实现异常处理的方式&#xff0c;这种方式使得异常处理的关注点与应用程序逻辑分离。 利用ControllerAdvice批注&#xff0c;我们能够为所有控制器创建一个全局帮助器类。 通过添加用ExceptionHandler和ResponseStatus注释的方法…

html.action 访问分部视图,MVC+EF 随笔小计——分部视图(Partial View)及Html.Partial和Html.Action差异...

Partial View指可以应用于View中以作为其中一部分的View的片段(类似于之前的user control), 可以像类一样&#xff0c;编写一次&#xff0c; 然后在其他View中被反复使用。一般放在"Views/Shared"文件夹中以共享。创建Partial View&#xff1a;一般直接右键"Vie…

svm核函数gamma参数_非线性SVM与核函数

前面几篇我们介绍的都是线性支持向量机&#xff0c;换句话说&#xff0c;我们总可以用一条线或一个超平面将数据进行分割。如下图所示&#xff1a;但在更多情况下&#xff0c;有些数据是无法进行线性分割的。比如下面的例子&#xff1a;也就是说&#xff0c;你永远无法用一条直…

a查询计算机主机路由表信息,计算机网络主机A向其他主机B进行通信的流程

当主机A要与主机B通信时&#xff0c;地址解析协议可以将主机B的IP地址如(192.168.1.2)解析成主机B的MAC地址&#xff0c;以下为工作流程&#xff1a;第1步&#xff1a;根据主机A上的路由表内容&#xff0c;IP确定用于访问主机B的转发IP地址是192.168.1.2。然后A主机在自己的本地…

使用Java将数据流式传输到HPCC

高性能计算集群&#xff08;HPCC&#xff09;是类似于Hadoop的分布式处理框架&#xff0c;除了它运行以自己的称为企业控制语言&#xff08;ECL&#xff09;的特定领域语言&#xff08;DSL&#xff09;编写的程序外。 ECL很棒&#xff0c;但是偶尔您会想用其他语言来执行繁重的…

anychart说明文档

今天学习anychart&#xff0c;在慧都控件网上看有关文档&#xff0c;模仿试着做了个demo&#xff0c;发现慧都空间网的“Flash图表AnyChart应用教程六&#xff1a;创建圆形仪表”里的指针“<pointer type"bar" value"35" color"Gray" />”…

h5 神策埋点_咕咚技术总监唐平麟:神策使我们的数据平台成本降低约 75%,迭代效率提升 2~3 倍...

在这个数据爆炸的时代&#xff0c;数据成为各行各业出奇制胜的法宝&#xff0c;运动行业也不例外&#xff0c;那么大数据对运动业有什么价值呢&#xff1f;咕咚作为智能运动的倡导者和先行者&#xff0c;致力于成为全球领先的运动大数据和服务平台&#xff0c;现已为超过 1.5 亿…

JavaFX,Jigsaw项目和JEP 253

因此&#xff0c; Java 9可能会破坏您的代码 …… 如果您的项目使用JavaFX&#xff0c;则这尤其可能&#xff0c;因为许多自定义项和自制控件都需要使用内部API。 借助Project Jigsaw&#xff0c;这些内容将无法在Java 9中访问。幸运的是&#xff0c; Oracle在几天前宣布了 JE…

微型计算机技术6,微型计算机技术课后习题6-8章答案.ppt

微型计算机技术课后习题6-8章答案MOV AL L2: MOV CX,8 L1: OUT 20H,AL CALL DELAY2S ROR AL,1 LOOP L1 JMP L2 习题:8.24 8253A-5的计数通道0连接如图习8-4所示,试回答:(1)计数通道0工作于何种方式&#xff0c;并写出工作方式名称&#xff1b;(2)写出计数通道0的计数初值(列出计…

免费的.NET混淆和反编译工具

免费的.NET代码混淆工具&#xff1a; Eazfuscator.NET http://www.foss.kharkov.ua/g1/projects/eazfuscator/dotnet/Default.aspx Skater .NET Obfuscator Freeware Light Edition http://www.rustemsoft.com/freeware_obfuscator.htm VisualStudio2010中集成的Dotfuscator…

ios 获取是否静音模式_果粉感动:部分iOS“新功能”早已被安卓玩坏

一年一度的WWDC大会如期举行&#xff0c;今年不仅展示了全新的iOS、iPadOS以及macOS。当然&#xff0c;具体更新了什么相信早已经被各大媒体报道出来&#xff0c;本文并不是重复报道&#xff0c;相反的&#xff0c;iOS经过了13代的发展&#xff0c;有开创性的动作&#xff0c;也…

怎么把桌面计算机隐藏文件,怎么隐藏桌面文件夹名称?隐藏桌面图标下的文字的详细教程...

怎么隐藏桌面文件夹名称&#xff1f;桌面图标一多就会显得很凌乱&#xff0c;特别有的软件名称很长&#xff0c;那么有没有什么方法可以让桌面看起来很清爽呢&#xff1f;当然是有&#xff0c;去掉桌面应用的名称不就简洁清爽了&#xff1f;下面就教大家不利用第三方软件的情况…

Hazelcast入门指南第7部分

这是解释如何使用Hazelcast的系列文章的续篇。 如果一个人没有阅读其他六个帖子&#xff0c;请转到目录并阅读其他帖子。 不同的地图种类 Hazelcast的MultiMap打破了以前使用java.util.Collection接口的常规方式。 实际上&#xff0c;在我看来&#xff0c;MultiMap的概念完全打…

JS将指定的时间戳转为UTC时间

Js中获取时间戳可用var dayMiliseconds parseInt(new Date().valueOf());Js的时间戳单位为毫秒&#xff08;1s 1000 ms&#xff09;,下面是一个将制定的格式转化成UTC时间的函数。 //format the date string from webservice to UTC time; function toUTCtime(dateStr) {//Da…