实现在 Kotlin 中返回 Collection 的 Java 方法。

huangapple go评论84阅读模式
英文:

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:

  1. Why does using kotlin.collections.Collection not cause an error here?
  2. 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&lt;? extends GrantedAuthority&gt; getAuthorities();
  ...
}

I noticed Intellij generates this Kotlin code:

override fun getAuthorities(): MutableCollection&lt;out GrantedAuthority&gt; { ... }

... 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:

  1. Why does using kotlin.collections.Collection not cause an error here?
  2. What's the correct Kotlin return type that's equivalent to java.util.Collection?

答案1

得分: 4

  1. 为什么在这里使用 kotlin.collections.Collection 不会导致错误?

如果你不知道的话,在Kotlin中,可变和不可变的集合接口都会解析为Java中的一个接口。所以Kotlin的 CollectionMutableCollection 都对应Java中的 java.util.Collection,Kotlin的 ListMutableList 都对应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() 方法。

  1. 什么是与 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&lt;out E&gt; which means the interface is a producer of type E. As a consequence, having:

val col: Collection&lt;GrantedAuthority&gt; = ...

Is nearly the same as:

val col: MutableCollection&lt;out GrantedAuthority&gt; = ...

I say nearly because, while MutableCollection&lt;out ...&gt; 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&lt;? extends GrantedAuthority&gt;

Is the following Kotlin type:

MutableCollection&lt;out GrantedAuthority&gt;

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&lt;GrantedAuthority&gt;

答案2

得分: 3

这能够正常工作的原因是 CollectionMutableCollection 都等同于 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.

huangapple
  • 本文由 发表于 2020年7月28日 15:13:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63128815.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定