在 Scala 中使用 Java 类 的有界通配符编译错误

Compilation error with bounded wildcards using Java classes in Scala

在Java中,我们这样定义了一个ObservableCollection.java

public class ObservableCollection<T> implements Collection<T> {

   public SubscriptionHandle onElementAdded(Consumer<T> onAdded) {
     // ... 
   }
}

还有一个 AgentService.java,returns 一个 ObservableCollection:

public interface AgentService {

    ObservableCollection<? extends Agent> getAgents();

}

现在,我正尝试在 Scala 项目中使用这个 ObservableCollection.java,如下所示:

  def test(service: AgentService): Unit = {
    val onAdded: Consumer[_ <: Agent] = ???
    service.getAgents.onElementAdded(onAdded)
  }

尝试此操作会导致以下编译错误:

type mismatch;
 found   : java.util.function.Consumer[_] where type _ <: com.xxxx.xx.xx.agent.Agent
 required: java.util.function.Consumer[?0] where type ?0 <: com.xxxx.xx.xx.agent.Agent
    service.getAgents.onElementAdded(onAdded)
                                     ^
one error found

这对我来说意义不大。有什么办法可以得到这个 运行?

编辑: 使用 Cosumer[Agent] 导致以下错误:

type mismatch;
 found   : java.util.function.Consumer[com.xxxx.xx.xx.agent.Agent]
 required: java.util.function.Consumer[?0] where type ?0 <: com.kuka.cc.si.agent.Agent
Note: com.xxxx.xx.xx.agent.Agent >: ?0, but Java-defined trait Consumer is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: ?0`. (SLS 3.2.10)
    service.getAgents.onElementAdded(onAdded)
                                     ^
one error found

这件事不在 Scala-Java 互操作中。以下 Scala 代码也无法编译

import java.util.function.Consumer
import java.util

trait Agent
trait SubscriptionHandle
trait AgentService {
  def getAgents: ObservableCollection[_ <: Agent]
}
trait ObservableCollection[T] extends util.Collection[T] {
  def onElementAdded(onAdded: Consumer[T]): SubscriptionHandle
}

def test(service: AgentService): Unit = {
  val onAdded: Consumer[_ <: Agent] = ???
  val agents: ObservableCollection[_ <: Agent] = service.getAgents
  agents.onElementAdded(onAdded)
//                      ^^^^^^^
}

//type mismatch;
// found   : java.util.function.Consumer[_] where type _ <: App.Agent
// required: java.util.function.Consumer[_]

你误用了存在类型(通配符泛型)。以下代码无法编译

trait X[T]
trait Y[T] {
  def foo(x: X[T]) = ???
}
val x: X[_] = ???
val y: Y[_] = ???
y.foo(x) // doesn't compile

xy 都具有存在类型,但 foo 接受类型 X[T]x,其中 T 必须相同因为 Ty 的类型中,即 Y[T],所以你不能保证 T 是相同的。

修复编译的一种方法是将泛型添加到 AgentService

trait Agent
trait SubscriptionHandle
trait AgentService[T <: Agent] {
  def getAgents: ObservableCollection[T]
}
trait ObservableCollection[T] extends util.Collection[T] {
  def onElementAdded(onAdded: Consumer[T]): SubscriptionHandle
}

def test[T <: Agent](service: AgentService[T]): Unit = {
  val onAdded: Consumer[T] = ???
  val agents: ObservableCollection[T] = service.getAgents
  agents.onElementAdded(onAdded)
}

或其方法

trait Agent
trait SubscriptionHandle
trait AgentService {
  def getAgents[T <: Agent]: ObservableCollection[T]
}
trait ObservableCollection[T] extends util.Collection[T] {
  def onElementAdded(onAdded: Consumer[T]): SubscriptionHandle
}

def test[T <: Agent](service: AgentService): Unit = {
  val onAdded: Consumer[T] = ???
  val agents: ObservableCollection[T] = service.getAgents
  agents.onElementAdded(onAdded)
}