总览

关于Java的不足之处(从C开发人员的角度来看)的一个有趣的文档是在一段时间(大约2000年前)写的,但是今天许多论点都像十年前一样真实(或不真实)。
原始的Java Sucks发布。

短消息回顾

Java没有free()。
作者将其列为受益,并且有99%的时间是胜利。 有时候,当您希望进行逃避分析时,没有不利之处 会立即消除,回收或释放您不再需要的对象(恕我直言,JIT / javac应该能够在理论上解决该问题)

词法范围的局部函数
最接近的Java是匿名方法。 对于Closures(Java 8中引入)来说,这是一个差的表亲,但是可以使它做同样的事情。

没有宏系统
您可以使用宏执行许多有用的技巧,Java可以动态地为您执行。 不需要宏系统是一种资产,因为您不需要知道Java何时会为您提供相同的优化。 宏没有应用程序启动成本,并且您无法做真正混淆的事情,但这可能是一件好事。

显式内联函数
JIT可以为您内联方法。 Java可以从共享库内联方法,即使它们是动态更新的。 这确实需要花费运行时间,但是更好的是不必担心此恕我直言。

我发现缺少函数指针是一个巨大的痛苦
函数指针使衬里方法对于编译器更加困难。 如果您使用的是面向对象的编程,那么我认为您不需要这些。 对于其他情况,我相信Java 8中的Closure可能会更好。

静态方法不是真正的类方法的事实是相当愚蠢的
我想大多数Java开发人员都会在某个阶段遇到此问题。 恕我直言:最好的解决方案是将“静态”功能移至其自己的类,并且如果需要多态性则不使用静态方法。

人们如何暗示应该内联一个方法,否则很快就会真正实现,这远非显而易见。
缩小并多次调用。 ;)

两个相同的byte []数组不相等且不散列相同
我同意它的丑陋设计选择不使数组成为合适的对象。 它们继承自Object,但没有toString,equals,hashCode,compareTo的有用实现。 clone()和getClass()是最有用的方法。 您可以改用辅助方法,但是在不同的程序包中有许多不同的辅助类,分别称为Array,Arrays,ArrayUtil,ArrayUtils,这对于新开发人员来说是一团糟。

Hashtable / HashMap确实允许您提供哈希函数
如果您想更改行为,这也是一种痛苦。 恕我直言,最好的解决方案是编写一个实现equals / hashCode的包装器类,但这会增加开销。

迭代字符串中的字符,而不隐式涉及每个字符的六个方法调用
现在有String.toCharArray(),但这会创建您不需要的副本,并且不会被转义分析消除。 如果是这样,这是显而易见的解决方案。 同样的道理也适用于“另一种选择是先将String转换为byte [],然后迭代字节,以创建大量随机垃圾为代价”

在我确定没有非ASCII字符的情况下,Unicode支持会增加开销
Java 6为此提供了-XX:+ UseCompressedStrings解决方案。 不幸的是,Java 7放弃了对该功能的支持。 我不知道为什么要在我做的测试中使用此选项来提高性能(以及减少内存使用)。

接口似乎是一个庞大而俗气的铜版画,可避免多重继承。 他们似乎真的是事后被嫁接了。
我更喜欢只列出所提供功能而不添加实现的合同。 Java 8中更新的虚拟扩展方法将提供无状态的默认实现。 在某些情况下,这将非常有用。

类型提升有些麻烦
Java 5.0+现在支持的协变量返回类型解决了这里的问题。

您不能编写一个期望和对象的函数并给它一个简短的描述
今天,您可以进行自动装箱。 作者抱怨说Short和short不是一回事。 出于效率目的,在某些情况下,使用自动装箱可能几乎没有什么区别。 在某些情况下,它确实有很大的不同,而且我不认为Java在不久的将来会对此进行透明地优化。 :|

如果不知道数组内容的详细信息,就无法遍历数组的内容,这是一种总的痛苦。
很少有您真正需要执行此恕我直言。 您可以使用Array.getLength(array)Array.get(array,n)处理通用数组。 它很丑,但是你可以做到。 它是辅助类之一,它实际上应该是数组本身的方法恕我直言。

处理溢出的唯一方法是使用BigInteger(并重写代码)
诸如Scala之类的语言支持BigInteger的运算符,并且有人建议Java也应如此。 我相信Java 8/9也将考虑溢出检测。

我想念typedef
这使您可以使用基元并仍然获得类型安全性。 恕我直言,真正的问题是JIT无法检测到类型仅仅是原语(或两个)的包装,并且不需要包装的类。 这将提供typedef的优点,而无需更改语法,并使代码更面向对象。

我认为用于模拟枚举和:keywords的可用习语相当la脚
Java 5.0+具有枚举 ,它们是一流的对象,并且功能强大。

没有有效的方法来实现“断言”
assert现在已内置。JIT可以自己实现它。 (大概不是十年前)

通过使“新”成为分配的唯一可能接口,……就有了一整类古老的,众所周知的优化,人们根本无法执行。
这应该由JIT IMHO执行。 不幸的是,它很少这样做,但是这种情况正在改善。

敲定系统很la脚。
大多数人都认为最好避免。 也许它可能更强大,更可靠。 答案可能是ARM(自动资源管理)。

相关地,没有“弱指针”。
Java一直都有弱,软和幻像引用,但是我怀疑这不是这里的意思。 ??

除了内部变量中的最终变量,您什么都不能关闭!
匿名内部类是正确的,但引用字段的嵌套内部类则没有。 封闭可能没有此限制,但可能同样令人困惑。 由于习惯了最终变量的要求,我尤其没有发现这个问题。 因为我的IDE会根据我的要求更正代码。

关于对象的可变性(或只读性)的访问模型受到打击
主要的抱怨似乎是有一些方法可以将最终字段视为可变的。 这是反序列化和依赖注入程序所必需的。 只要您意识到自己有两个可能的行为,一个级别比另一个级别低,它就会比问题更有用。

该语言还应规定字面常量是不变的。
文字常量是不可变的。 看来作者想扩展什么是文字常量。 恕我直言,以C ++的方式支持const很有用。 const是Java中的关键字,而无需创建多个实现或只读包装器来定义类的不可变版本的功能将更有效率。

锁定模型已损坏。
锁定问题的内存开销实际上是一个实现细节。 由JVM决定标头的大小以及是否可以锁定标头。 另一个问题是无法控制谁可以获取锁。 解决此问题的常用方法是封装您的锁,这是您在任何情况下都必须要做的。 从理论上讲,锁可以被优化掉。 当前,只有在优化整个对象时才会发生这种情况。

没有抛出就没有信号
为此,我将侦听器模式与onError方法一起使用。 语言对此没有支持,但我认为没有必要。

应该将foo.x定义为等同于foo.x(),
也许foo.x => foo.getX()会是更好的选择,就像C#一样。

编译器应该能够轻松地内联零参数访问器方法,以内联对象+偏移量加载。

JIT这样做,而不是编译器。 这样就可以在编译被调用方之后更改调用代码。

方法“属于”类的概念是la脚的。
这是某些语言支持的“酷”功能。 在更动态的环境中,这看起来更好。 不利的一面是,您可以在整个地方为某个类编写一段代码,并且您将不得不采用某种方式来管理不同库中的重复项。 例如,库A定义了一个新的printString()方法,库B也为同一类定义了一个printString方法。 您将需要使每个库看到其自己的副本,并具有某种方法来确定C调用此方法时需要哪个版本的库。

图书馆

它带有哈希表,但没有qsort
它带有一个“优化的合并排序”,旨在加快速度。

字符串的长度为+ byte []的开销+24个字节
也就是说,无需考虑两个对象中的每个对象都与8字节边界对齐(使其更高)。 如果听起来很糟糕,请考虑将malloc对齐16字节,最小大小为32字节。 如果将shared_ptr用作byte [](以提供类似的资源管理),则在C ++中,它可能比Java大得多。

造成这种开销的唯一原因是String.substring()可以返回共享相同值数组的字符串。

这是不正确的。 问题是Java不支持可变大小的对象(数组除外)。 这意味着String对象是固定大小的,要拥有可变大小的字段,您必须拥有另一个对象。 无论哪种方式都不是很好。 ;)

String.substring可能是“内存泄漏”的来源
您必须知道要对您进行显式复制,才能保留较大字符串的子字符串。 这很丑陋,但是好处通常超过了缺点。 更好的解决方案是能够优化代码,以便默认情况下采用防御性副本,除非不需要防御性副本(已将其优化掉)

文件操作原语不足
Java 7中改进了文件系统信息。我认为这些选项不可用,但是如果您需要知道这些选项,则可以很容易地推断出它们。

这不是问“我在Windows上运行”还是“我在Unix上运行”的可靠方法。
系统属性os.name,os.arch,os.version一直存在。

在Unix上无法访问link(),这是实现文件锁定的唯一可靠方法。
这是在Java 7 创建硬链接中添加的

除了复制并重命名整个文件外,没有其他方法可以执行ftruncate()。
您可以使用RandomAccessFile.truncate()。 在Java 1.4中添加。

“%10s%03d”真的有太多要求吗?
它是在Java 5.0中添加的

RandomAccessFile不能用作FileInputStream或FileOutputStreamRandomAccessFile

支持DataInput和DataOutput,FileInputStream和FileOutputStream可以包装在DataInputStream和DataOutputStream中。 可以使它们支持相同的接口。 我从未遇到过要在单个方法中同时使用两个类的情况。

markSupported是愚蠢的
真正。 有许多愚蠢的方法只是出于历史目的。 另一个是在每个对象(甚至数组)上的Object.wait(millis,nanos ),但是nanos从未真正使用过。

世界和系统运行时之间有什么区别?
我同意这似乎是任意的,在某些情况下会增加一倍。 System.gc()实际上调用Runtime.getRuntime()。gc(),但即使在内部代码中也被称为System GC。 在后站点中,它们实际上应该是一类,并将监视功能移至JMX。

世界上是在基础语言类库中进行的像checkPrintJobAccess()这样的应用程序级废话
因此,您的SecurityManager可以控制是否可以执行打印。 (也不必具有应用程序级安全性管理器)不确定是否确实阻止了对应用程序级安全性的需求。 ;)

参考:在Java Java博客上,我们的JCG合作伙伴 Peter Lawrey 重新审视了“ Java Sucks” 。

翻译自: https://www.javacodegeeks.com/2012/01/java-sucks-revisited.html

重温“ Java Sucks”相关推荐

  1. Why Java Sucks and C# Rocks(3):Attribute与Annotation

    上一篇文章里我谈了Java和C#语言中对于基础类型的不同态度,我认为C#把基础类型视做对象的做法比Java更有"万物皆对象"的理念,使用起来也更为方便.此外,C#拥有一个Java ...

  2. 幻灯片:Why Java Sucks and C# Rocks

    昨天在5173与博客园联合举办的技术交流活动中进行了演讲,现在幻灯片终于可以放出了.当然,光看幻灯片本身的效果不大,在演讲过程中我进行了非常多的代码演示和说明,幻灯片本身只能算是一个辅助手段,因此各位 ...

  3. 重温java中的String,StringBuffer,StringBuilder类

    不论什么一个系统在开发的过程中, 相信都不会缺少对字符串的处理. 在 java 语言中, 用来处理字符串的的类经常使用的有 3 个: String.StringBuffer.StringBuilder ...

  4. 重温java web过滤器filter

    点击上方"好好学java",选择"置顶公众号" 优秀学习资源.干货第一时间送达! 精彩内容 java实战练习项目教程 2018微服务资源springboot.s ...

  5. java 模板函数_重温Java中的模板方法设计模式

    Java 8 lambda表达式的简洁性为经典的GoF设计模式提供了新的视角.通过利用函数式编程,我们可以通过更少的耦合获得相同的好处 - 模板方法就是一个很好的例子. 经典的GoF模板方法实现 模板 ...

  6. 重温java知识(三十九、JUC并发编程之五:线程锁之StampedLock【无障碍锁】)

    读/写锁可以保证并发访问下的数据写入安全与读取性能,但是在读线程非常多的情况下,有可能造成写线程的长时间阻塞,从而减少写线程的调度次数.为此JUC中针对读/写锁提出了改进方案,提供了无障碍锁(Stam ...

  7. 温故而知新,重温 Java 7 的那些“新”特性

    2009 年 4 月 20 日,Java 的亲生父亲 Sun 被养父 Oracle 以 74 亿美元收购,这在当时可是一件天大的事.有不少同学都担心 Java 的前途,我当时傻不啦叽地也很担心:自己刚 ...

  8. 重温Java基础(五)

    1.抽象类与接口 1.1.抽象方法,abstract修饰的方法,特点如下, 抽象方法是没有方法体,abstract Double getArea(); 抽象方法必须定义在抽象类中 子类必须去覆盖该方法 ...

  9. java文档表白_java基础io流——File的告白(重温经典)

    File类概述和构造方法 File类的概述 文件和目录路径名的抽象表示形式 构造方法 public File(String pathname) public File(String parent,St ...

最新文章

  1. 5分钟速通 AI 计算机视觉发展应用
  2. sudo: apt-get:找不到命令_Linux重复执行历史命令方法详解
  3. python快速入门课堂笔记_Python 快速入门笔记(9):模块和包
  4. struts1起服务报错
  5. dell 重装linux系统_U盘装系统开机按哪个键
  6. [转] C#2010 在TreeView控件下显示路径下所有文件和文件夹
  7. Lesson4 一阶方程代换法
  8. Net设计模式实例之组合模式(Composite Pattern)(3)
  9. 大学物理计算机仿真实验报告,大学物理实验实验报告模板.doc
  10. android re浏览器下载,re浏览器官方版下载_re浏览器app下载4.9.6 - 系统城
  11. 编程实现之k均值算法
  12. 【UCSC Genome Browser】- ClinGen剂量敏感性分析
  13. Justinmind使用教程(1)——概述部分
  14. 2021年全球无水氢氟酸收入大约3120.8百万美元,预计2028年达到3634.6百万美元
  15. 2021考研肖秀荣大纲解读及复习建议
  16. 成都传智播客java培训中心
  17. 【深度域适配】一、DANN与梯度反转层(GRL)详解
  18. 帆软报表列表_帆软入门与报表设计
  19. 【aspose】 word/excel转pdf,实现在线预览文件功能
  20. 淘宝技术这十年 知识点

热门文章

  1. redis 受攻击怎么办?_最受欢迎的6个最常用的Redis库
  2. selenium自动化测试_使用Selenium自动化测试处理多个浏览器选项卡
  3. 2018-12 jdk_JDK 12新闻(2018年9月13日)
  4. c 应用程序开发框架_企业应用程序开发框架的分类
  5. java redis 命令_命令界面:使用Java中的动态API处理Redis
  6. java基准测试_微基准测试进入Java 9
  7. antlr idea 入门_ANTLR入门:构建简单的表达语言
  8. jooq 配置oracle_jOOQ配置
  9. 使用适用于Java 2的AWS开发工具包的AWS DynamoDB版本字段
  10. 如何在Java中修复表达式的非法开头