英文:
Implement Java method that returns Collection in Kotlin
问题
I noticed Intellij generates this Kotlin code:
override fun getAuthorities(): MutableCollection<out GrantedAuthority> { ... }
... which makes sense since java.util.Collection
is mutable.
However, if I replaced the MutableCollection
with Collection
(which should be kotlin.collections.Collection
IIRC), the code still compiles fine. This confuses me because kotlin.collections.Collection
is a read-only interface that MutableCollection
inherits from. It doesn't make sense that I can return an immutable collection for a method that's declared to return a mutable collection.
So my questions are:
- Why does using
kotlin.collections.Collection
not cause an error here? - What's the correct Kotlin return type that's equivalent to
java.util.Collection
?
英文:
I'm using Kotlin with Spring Security. When implementing this method:
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
...
}
I noticed Intellij generates this Kotlin code:
override fun getAuthorities(): MutableCollection<out GrantedAuthority> { ... }
... which makes sense since java.util.Collection
is mutable.
However, if I replaced the MutableCollection
with Collection
(which should be kotlin.collections.Collection
IIRC), the code still compiles fine. This confuses me because kotlin.collections.Collection
is a read-only interface that MutableCollection
inherits from. It doesn't make sense that I can return an immutable collection for a method that's declared to return a mutable collection.
So my questions are:
- Why does using
kotlin.collections.Collection
not cause an error here? - What's the correct Kotlin return type that's equivalent to
java.util.Collection
?
答案1
得分: 4
- 为什么在这里使用
kotlin.collections.Collection
不会导致错误?
如果你不知道的话,在Kotlin中,可变和不可变的集合接口都会解析为Java中的一个接口。所以Kotlin的 Collection
和 MutableCollection
都对应Java中的 java.util.Collection
,Kotlin的 List
和 MutableList
都对应Java中的 java.util.List
,以此类推。
此外,Kotlin有所谓的声明-site variance(声明-site变异)。Kotlin的 Collection
接口被定义为 Collection<out E>
,这意味着该接口是类型 E
的生产者。因此,拥有以下代码:
val col: Collection<GrantedAuthority> = ...
几乎等同于:
val col: MutableCollection<out GrantedAuthority> = ...
我说几乎,因为虽然 MutableCollection<out ...>
阻止了任何人向集合添加任何元素,但它并不阻止对集合进行完全的修改。例如,你仍然可以在集合上调用 clear()
方法。
- 什么是与
java.util.Collection
等效的正确Kotlin返回类型?
Java没有声明-site变异。它也不区分可变和不可变的集合(至少在接口级别上不区分)。
这意味着,从技术上讲,以下Java类型的最佳匹配:
Collection<? extends GrantedAuthority>
是以下Kotlin类型:
MutableCollection<out GrantedAuthority>
这两种类型都是可变集合类型,并且被定义为类型 GrantedAuthority
的生产者(通过Java中的 ? extends
和Kotlin中的 out
)。这两种类型都不允许你向集合添加任何内容。
然而,如果你的 getAuthorities()
方法应该返回一个不可修改的集合(例如,在Java中使用 Collections.unmodifiableCollection(collection)
),那么从Java到Kotlin的更合适的转换应该是:
kotlin.collections.Collection<GrantedAuthority>
英文:
>1. Why does using kotlin.collections.Collection
not cause an error here?
If you're not aware, the mutable and non-mutable collection interfaces in Kotlin both resolve to one interface in Java. So Kotlin's Collection
and MutableCollection
are both java.util.Collection
in Java, Kotlin's List
and MutableList
are both java.util.List
in Java, and so on.
Also, Kotlin has what it terms declaration-site variance. The Kotlin Collection
interface is defined as Collection<out E>
which means the interface is a producer of type E
. As a consequence, having:
val col: Collection<GrantedAuthority> = ...
Is nearly the same as:
val col: MutableCollection<out GrantedAuthority> = ...
I say nearly because, while MutableCollection<out ...>
prevents anyone from adding any elements, it does not prevent one from mutating the collection entirely. For example, you could still call clear()
on the collection.
>2. What's the correct Kotlin return type that's equivalent to java.util.Collection
?
Java does not have declaration-site variance. It also doesn't distinguish between mutable and non-mutable collections (at least not at the interface level).
This means that, technically, the best match of the following Java type:
Collection<? extends GrantedAuthority>
Is the following Kotlin type:
MutableCollection<out GrantedAuthority>
Both types are mutable collection types and are defined to be producers of type GrantedAuthority
(via ? extends
in Java and out
in Kotlin). Neither type let's you add anything to the collection.
However, if your getAuthorities()
method is supposed to return an unmodifiable collection (e.g. Collections.unmodifiableCollection(collection)
in Java) then the more appropriate conversion from Java to Kotlin would be to use:
kotlin.collections.Collection<GrantedAuthority>
答案2
得分: 3
这能够正常工作的原因是 Collection
和 MutableCollection
都等同于 java.util.Collection
。你可以在这里查看所有与Java互操作性映射的Java类型的完整列表。
这能够正常工作是因为非可变集合接口实际上并不是不可变的(要实现不可变集合,你需要使用不可变集合库),而是提供了只读接口(正如你所指出的)。由于Java没有这种区分,因此两者都必须映射到相同的Java平台类型。
与
java.util.Collection
等效的正确Kotlin返回类型是什么?
正确的返回类型取决于您想要向Kotlin客户端公开的接口。如果他们不应该对返回的集合进行更改,请使用 Collection
。如果您希望他们能够对其进行更改,请使用 MutableCollection
。对于Java客户端,这并不重要:它们是等效的。
英文:
The reason that this works is that Collection
and MutableCollection
are both equivalent to java.util.Collection
. You can see the full list of Java types that are mapped for Java interop here.
This works because the non-mutable collection interfaces aren't actually immutable (for that, you'd want the Immutable Collections Library), but they simply provide a read-only interface (as you note). Since Java doesn't make this distinction, both have to be mapped to the same Java platform type.
> What's the correct Kotlin return type that's equivalent to java.util.Collection
?
The correct return type depends on the interface you want to expose to your Kotlin clients. If they shouldn't be mutating the returned collection, use Collection
. If you expect them to want to mutate it, use MutableCollection
. For your Java clients, it doesn't matter: they're equivalent.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论