小编典典
92
Skiwi的答案已经涵盖了许多要点。我会再填一些背景。
任何API的设计都是一系列折衷。在Java中,困难的问题之一是处理很久以前做出的设计决策。
从1.0开始,基元就已经在Java中使用。它们使Java成为“不纯的”面向对象的语言,因为基元不是对象。我相信添加原语是一个务实的决定,它以牺牲面向对象的纯度为代价来提高性能。
这是将近20年后的今天,我们仍然需要权衡的问题。Java 5中添加的自动装箱功能主要消除了使用装箱和拆箱方法调用使源代码混乱的问题,但开销仍然存在。在许多情况下,它并不明显。但是,如果要在一个内部循环中执行装箱或拆箱,您会发现它会带来大量的CPU和垃圾回收开销。
在设计Streams API时,很明显,我们必须支持原语。装箱/拆箱的开销会扼杀并行性带来的任何性能优势。但是,我们并不想支持所有的原语,因为那样会给API增加很多麻烦。(您真的看到了“ a”的用法ShortStream吗?)“全部”或“无”是设计的理想位置,但都不可接受。因此,我们必须找到“ some”的合理值。我们结束了与原始的专长int,long和double。(就我个人而言,我会被排除在外,int但那只是我。)
因为CharSequence.chars()我们考虑过退货Stream(早期的原型可能已经实现了),但由于装箱费用而被拒绝。考虑到字符串具有char作为原始值的字符串,当调用者可能只是对该值进行一点处理并将其重新装箱回到字符串中时,无条件施加装箱似乎是一个错误。
我们还考虑了CharStream原始的专业化,但是与它添加到API的批量数量相比,它的使用似乎非常狭窄。似乎没有必要添加它。
这给调用者带来的代价是,他们必须知道IntStream包含char表示为的值,ints并且必须在正确的位置进行转换。这使人们倍感困惑,因为有大量的API调用,例如PrintStream.print(char)和PrintStream.print(int),其行为明显不同。可能会引起另一个混乱点,因为该codePoints()调用还会返回一个,IntStream但其中包含的值却大不相同。
因此,这归结为在几种选择中务实地选择:
我们无法提供原始的专业知识,因此会产生简单,优雅,一致的API,但会带来高性能和GC开销;
我们可以提供一套完整的原始专业知识,但代价是使API混乱不堪,并给JDK开发人员带来了维护负担;要么
我们可以提供原始专业化的子集,从而提供中等大小的高性能API,从而在相当狭窄的用例范围(字符处理)中为调用者带来相对较小的负担。
我们选择了最后一个。
2020-11-06