RandomAccess 接口,为啥没有方法?

Posted

技术标签:

【中文标题】RandomAccess 接口,为啥没有方法?【英文标题】:RandomAccess Interface, Why no methods?RandomAccess 接口,为什么没有方法? 【发布时间】:2012-11-25 02:35:51 【问题描述】:

我在看Collections.shuffle(List) javadoc,然后看了RandomAccess javadoc:

List 实现使用的标记接口来指示它们 支持快速(通常是恒定时间)随机访问。 [...]

我想知道为什么这个接口(如 Serializable)没有方法?这样做的设计原因是什么?

即使只是Lists“实现”这个接口,为什么不设置Eget()作为方法呢?我知道不是每个列表都是随机访问的,但是如果没有方法,我该如何使用这个接口?

类似这样的:

if(object instanceof RandomAccess)
    // should I cast it if no operations can be done? why?

另外,只有Lists可以是RandomAccess?文件呢?

【问题讨论】:

正如 javadoc 所说,它是一个 "marker" 接口,并且根据定义不会有方法。它标记了具有快速随机访问的 List 实现,因此使用该实现的人会知道他们正在使用的类已经过优化。 【参考方案1】:

“标记”接口是一种早于注释的技术;它旨在将一个类标记为符合某个标准,而该标准与方法无关。

在这种情况下,随机播放可能会对不支持快速随机访问的列表采取不同的方式。考虑如何打乱一个链表;这很难,对吧?你不能只说“给我一个随机元素”而不遍历列表,跟随指向下一个元素的指针。现在将其与 ArrayList 进行对比。由于列表的存储方式,获取随机元素要容易得多。

没有办法在方法名称中限定“列表的存储方式”或“不同的访问模式可能有多快或多慢”。因此,Java 使用标记接口来提供此信息。

在这种情况下,ArrayList 将是一个 RandomAccess,而 LinkedList 不是。

编辑

那些对标记接口和标记注释之间的区别感兴趣的人会喜欢 Joshua Bloch 在 Effective Java 2nd Edition 中的第 37 条:“使用标记接口定义类型”。

【讨论】:

我认为拒绝获取列表不适合随机播放的代码(因为它已经实现了获取列表的方法)。但它可能会为链表选择不同的算法(比如先复制链表,或者做一个不需要随机访问的算法)。 我会说,对于标记接口,它与标准或合同无关,因为它与方法中反映的行为有关,而更多地与类的实现有关。否则很好的答案。 @CoryKendall 我仍然不清楚基本概念。为什么要实现 RandomAccess?甚至 Array 由于连续内存而提供更快的访问,而 ArrayList 在内部使用数组,那么这应该足以使其更快,对吗? JVM 是否为实现 RandomAccess 的列表做任何额外的事情?【参考方案2】:

这是一个标记界面。它定义了不使用任何额外方法的行为或能力。

在这种情况下,它表示随机访问(已经在 List 接口中定义)不仅是可能的,而且是有效的。使用List的代码可以根据这个在算法之间切换。

人们可以争论这是否是一个好的设计决策。例如,随机访问方法可能已从 List 中删除(仅允许迭代),而是放入 RandomAccess 接口中。同样,对象序列化系统的方法也可以放在 Serializable 接口中。

另外,只有Lists可以是RandomAccess?

我猜这个接口也可以用来做其他事情,但看起来它目前只被列表使用。

文件呢?

随机访问文件有一个单独的机制 (java.io.RandomAccessFile)。

【讨论】:

以上是关于RandomAccess 接口,为啥没有方法?的主要内容,如果未能解决你的问题,请参考以下文章

RandomAccess是什么

死磕JDK源码之ArrayList

小白学Java:奇怪的RandomAccess

RandomAccess标记接口

RandomAccess接口

RandomAccess接口