为什么Java编程语言数组不像常规类那样,例如它不能继承而且它的类中没有任何实用方法(例如像String
)?
可以为阵列设计许多方法,例如
swap()
,搜索方法,排序方法,拆分/拼接方法等。
答案 0 :(得分:6)
这主要是出于历史原因。
从一开始就将数组(和被处理)视为特殊数据类型,例如distinct VM opcodes that were intended to deal only with them(请注意,数组处理的操作码实际上只有吨!)。它主要是这样制作的,因此阵列的性能接近原生(以便JNI可以轻松地与它们交互)。这里的设计选择是需要快速/内存有效的原始/数组数据类型,然后才需要一个美丽的"接口,因此既不是原语也不是数组都不是真实的"用于VM性能的对象。
虽然Oak Language Specification(橡树是直接的Java祖先)陈述Although arrays can be created with new, just as instances of classes are created, arrays are not currently objects.
是古代(约20岁),但它仍然显示了这种表现的总体思路-elegance tradeoff - 大约15年后在Oracle自己的Arrays 2.0 talk中对当代Java重申的想法,给出了一个很好的见解,为什么它是这样的,什么可以我们期望它在不久的将来。我将突出显示关于为什么的五美分。
首先,有时阵列会更好,因为假的"对象而不是"真实"一个,例如当数组只是内联到方法代码时(与局部变量一样),there are some cases(本地数组包含< = 64元素)。使它们成为常规类会使这些优化变得更加困难。然而,缺点是它排除了常规"类/对象的使用 - 因为有一个"常规"类/对象行为将要求运行时处理所有事情,例如虚拟调度,对象构造函数,具有组合图等的GC,会导致运行时损失(请参阅脚注以获得注释)。请注意String
没有这些问题,因为它只是一个语法糖封面的char[]
封装类!
此外,请注意您不能,例如只是"排序" 一个数组 - 有许多排序算法可以使用,所以数组类应该已经了打开(可重载等),如果添加了这些实用程序。甚至更多 - 这样的接口的正确设计(和是,如C#中所见)非常棘手(由于例如多维度数组,可空与非空数组,可能的循环引用等),这可能会使事情更加复杂化。 OTOH,改变它可能会破坏向后兼容性 - 所以Java开发人员决定让它成为现实的方式更好。不久前我们有a bug with Java lib's own TimSort some time ago - 如果它包含在final
数组类中,它实际上会阻止程序员通过重写方法来修复它!
然而,实用程序类java.util.Arrays
(包含您可能需要的所有常见数组实用程序)和瘦包装类允许对数组进行适当的面向对象访问(例如{ {1}})。你甚至可以自己写一个,并给你ArrayList
你灵魂所需的任何东西;作为一名程序员,有时更多的是关于创建工具,而不是使用。
注意: 可以通过使用例如来实现对数组的类似于对象的行为。一个语法感知的源预处理器/词法分析器(以类似于Lombok的方式工作)或者通过修补编译器,这反过来会将数组上的伪调用重写为有效的静态方法,传递数组作为参数;例如给定类似于ArrayWrapper
的定义,它会将@ArrayEx(Arrays.class) int[] array;
之类的命令转换为array.sort();
- 然而,解释Eric Lippert,它不在那里,因为没有人打扰它编码< / em>的。如果您因任何原因发现自己迫切需要它 - 只需编写代码并将修补程序提交给OpenJDK,甚至只需将其发布到GitHub上......主要是OSS如何工作轻笑 。 Project Valhalla在这里带来了一些希望,因为它至少与这个问题切线相关 - 你可能会说具有类似对象的原始值是铺平通往真实对象阵列的道路的好方法。前面提到的Arrays 2.0 talk实际上突出了当前的&#34;假的&#34;对象行为作为当前实现的缺点之一,提到我上面提到的一些事情,无论是有意识的开发选择,还是可能的机会和陷阱。总而言之,也许那些在Oracle / OpenJDK上的好人实际将在未来的Java扩展中添加它们,谁知道......