Java:Set接口和Collection接口的区别
我刚刚查找了 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 {}
现在,A
、B
或 C
之间有什么区别吗?
虽然合同(即文档中所说的内容)对于某些功能(例如 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从技术上讲,对于编译器来说,这没有任何区别。
但是,集合不能有重复的条目,而集合可以。这是值得了解的。
因此,参数、返回值和发生的情况的方法语义可能意味着不同的事情。重新声明还允许 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.)"
答案就在 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.)"
方法不仅仅是它的签名。
在这种情况下,这些方法的文档已根据前置条件和后置条件以及术语进行了定制。
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.
它们被重新声明,因为即使名称相同,它们也具有不同的含义。
Set
中的add
方法是Collection
中通用add
方法的特定实现代码>.其目的是明确指定
Set
的add
方法与Collection
的 add 方法有很大不同。为什么不直接将 Set 接口定义为:
如果这样做了,就没有地方可以指定
Set
的契约了。我怎么知道通过实现Set
的add
方法,我不应该允许重复项?They are redeclared because, even if the names are same, they have different meaning. The
add
method in theSet
is a specific implementation of the genericadd
method inCollection
.The intention is to explicitly specify that the
add
method os theSet
is very different from the add method ofCollection
.Why not just define the Set interface as:
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 theadd
method of theSet
, I should not allow duplicates?