Java:Set接口和Collection接口的区别

发布于 2024-09-28 10:58:27 字数 1859 浏览 0 评论 0原文

我刚刚查找了 Set 接口,发现它大部分(或完全)只重新声明了 Collection 接口中已有的函数。 Set 本身扩展了 Collection,所以这是否意味着 Set 接口自动拥有 Collection 中的所有功能?那么为什么要重新声明它们呢?

例如,Set 重新声明了以下内容:

/**
 * Returns the number of elements in this set (its cardinality).  If this
 * set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this set (its cardinality)
 */
int size();

/**
 * Returns <tt>true</tt> if this set contains no elements.
 *
 * @return <tt>true</tt> if this set contains no elements
 */
boolean isEmpty();

以及 Collection 中的声明:

/**
 * Returns the number of elements in this collection.  If this collection
 * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this collection
 */
int size();

/**
 * Returns <tt>true</tt> if this collection contains no elements.
 *
 * @return <tt>true</tt> if this collection contains no elements
 */
boolean isEmpty();

这对我来说似乎非常多余。为什么不直接将 Set 接口定义为:

public interface Set<E> extends Collection<E> {}

我认为这些接口之间没有任何区别,对吗?


当然,我不是在询问 Set 的不同语义/含义。我知道。我只是问它在技术上(即对编译器)是否有任何区别。也就是说,一般来说:

interface A { void foo(); }
interface B extends A { void foo(); }
interface C extends A {}

现在,ABC 之间有什么区别吗?


虽然合同(即文档中所说的内容)对于某些功能(例如 add)确实可能有所不同,但重新声明它们是有充分理由的:为了能够放置新文档,即定义新合同。

但是,也有一些函数(例如 isEmpty)具有完全相同的文档/合同。为什么它们也被重新声明?

I just looked up the Set interface and found that it mostly (or completely) only redeclares functions which are already in the Collection interface. Set itself extends Collection, so doesn't that mean that the Set interface automatically has all the functions from Collection? So why are they redeclared then?

For example, Set redeclares this:

/**
 * Returns the number of elements in this set (its cardinality).  If this
 * set contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this set (its cardinality)
 */
int size();

/**
 * Returns <tt>true</tt> if this set contains no elements.
 *
 * @return <tt>true</tt> if this set contains no elements
 */
boolean isEmpty();

And the declaration in Collection:

/**
 * Returns the number of elements in this collection.  If this collection
 * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
 * <tt>Integer.MAX_VALUE</tt>.
 *
 * @return the number of elements in this collection
 */
int size();

/**
 * Returns <tt>true</tt> if this collection contains no elements.
 *
 * @return <tt>true</tt> if this collection contains no elements
 */
boolean isEmpty();

This seems very redundant to me. Why not just define the Set interface as:

public interface Set<E> extends Collection<E> {}

I think there is no single difference between those interfaces, right?


Of course I am not asking about the different semantics / meaning of Set. I know that. I am just asking about if it technically (i.e. to the compiler) has any difference. I.e., speaking generally:

interface A { void foo(); }
interface B extends A { void foo(); }
interface C extends A {}

Now, is there any difference between A, B or C?


While the contract (i.e. what is said in the documentation) can really be different for some functions (as for add), there is a valid reason to redeclare them: To be able to put a new documentation, i.e. to define the new contract.

However, there are also functions (like isEmpty) which have exactly the same documentation / contract. Why are they also redeclared?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

已下线请稍等 2024-10-05 10:58:27

从技术上讲,对于编译器来说,这没有任何区别。

但是,集合不能有重复的条目,而集合可以。这是值得了解的。

因此,参数、返回值和发生的情况的方法语义可能意味着不同的事情。重新声明还允许 javadoc 变得更加具体。例如,对于 add():

Set:如果此集合尚未包含指定元素,则 @return true

集合:如果此集合因调用而更改,则 @return true

set 的含义更为具体。

即使对于不太具体的方法,它也使 javadoc 变得更好。例如,对于 size() :“返回此集合中的元素数量(其基数)。”这更接近于习惯数学集合的人们能够理解的语言。

API 文档对此进行了总结:“除了从 Collection 接口继承的规定之外,Set 接口还对所有构造函数的契约以及 add、equals 和 hashCode 方法的契约做出了额外的规定。其他继承的声明为了方便起见,此处还包含了方法(这些声明附带的规范已针对 Set 接口进行了定制,但它们不包含任何附加规定。)”

Technically for the compiler it makes no difference at all.

However, a set cannot have duplicate entries whereas a Collection can. This is worth knowing about.

Because of this, the methods semantics for parameters, return values and what happens can mean different things. Redeclaring also allows the javadoc to become more specific. For example for add():

Set: @return true if this set did not already contain the specified element

Collection: @return true if this collection changed as a result of the call

The meaning for set is more specific.

Even for methods that are not more specific, it enables the javadoc to be nicer. For example, for size() : "Returns the number of elements in this set (its cardinality)." which is closer to the language people used to mathematical sets will understand.

The API documents summarise this by saying: "The Set interface places additional stipulations, beyond those inherited from the Collection interface, on the contracts of all constructors and on the contracts of the add, equals and hashCode methods. Declarations for other inherited methods are also included here for convenience. (The specifications accompanying these declarations have been tailored to the Set interface, but they do not contain any additional stipulations.)"

纵情客 2024-10-05 10:58:27

答案就在 java6 API 中的 set 。

“除了从 Collection 接口继承的那些之外,Set 接口还对所有构造函数的契约以及 add、equals 和 hashCode 方法的契约做出了额外的规定。为了方便起见,这里还包含了其他继承方法的声明。(规范随附的这些声明已针对 Set 接口进行了定制,但它们不包含任何附加规定。)”

The answer is in the java6 API for set.

"The Set interface places additional stipulations, beyond those inherited from the Collection interface, on the contracts of all constructors and on the contracts of the add, equals and hashCode methods. Declarations for other inherited methods are also included here for convenience. (The specifications accompanying these declarations have been tailored to the Set interface, but they do not contain any additional stipulations.)"

メ斷腸人バ 2024-10-05 10:58:27

方法不仅仅是它的签名。

在这种情况下,这些方法的文档已根据前置条件和后置条件以及术语进行了定制。

There is more to a method than its signature.

In this case, the documentation of these methods has been tailored to sets, in terms of pre- and post-conditions, and terminology.

剑心龙吟 2024-10-05 10:58:27

它们被重新声明,因为即使名称相同,它们也具有不同的含义。 Set 中的 add 方法是 Collection 中通用 add 方法的特定实现代码>.

其目的是明确指定 Setadd 方法与 Collection 的 add 方法有很大不同。

为什么不直接将 Set 接口定义为:

public interface Set<E> extends Collection<E> {} 

如果这样做了,就没有地方可以指定 Set契约了。我怎么知道通过实现 Setadd 方法,我不应该允许重复项?

They are redeclared because, even if the names are same, they have different meaning. The add method in the Set is a specific implementation of the generic add method in Collection.

The intention is to explicitly specify that the add method os the Set is very different from the add method of Collection.

Why not just define the Set interface as:

public interface Set<E> extends Collection<E> {} 

If it has been done this way, there would be no place where the contract of a Set can be specified. How would I know that by implementing the add method of the Set, I should not allow duplicates?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文