【问题标题】:Compilation error with bounded wildcards using Java classes in Scala在 Scala 中使用 Java 类的有界通配符编译错误
【发布时间】:2020-12-13 02:43:25
【问题描述】:

在 Java 中,我们定义了一个 ObservableCollection.java,如下所示:

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

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

还有一个返回 ObservableCollection 的 AgentService.java

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[_$1] where type _$1 <: 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

【问题讨论】:

  • 错误是真实的还是只是在某些 IDE 中? - 如果你有Consumer[Agent],会发生什么? - 如果你像service.getAgents.asInstanceOf[ObservableCollection[Agent]](加上上一点)这样的脏演员会发生什么?
  • @LuisMiguelMejíaSuárez 这是真的。
  • 是的,错误是真实的。关于Consumer[Agent] 的用法:请参阅已编辑的问题。不过,有了脏演员,它就可以了!

标签: java scala type-conversion scala-java-interop bounded-wildcard


【解决方案1】:

问题不在 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[_$2] where type _$2 <: App.Agent
// required: java.util.function.Consumer[_$3]

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

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 必须与y 类型中的T 相同,即@ 987654331@,所以不能保证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)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    相关资源
    最近更新 更多