【问题标题】:Type Translation Issues类型翻译问题
【发布时间】:2017-06-27 14:04:12
【问题描述】:

我在 Java 中的类层次结构下面有这个

Class Container 
{
    private List<? extends Element> element;
    public List<? extends Element> getElements()
    {
        return elements;
    }

    public void setElements(List<? extends Element> elements)
    {
        this.elements = elements;
    }
}

MyElement extends Element 
{
 int a;
}

在我的 scala 服务中,我使用以下这些类 -

var elements: java.util.List[_ <: Element] = container getElements

elements match {
  case null => elements = new ArrayList[MyElement]();
  case _    => ;
}
//additional service code here, 
//and then try to create an object and add it to the existing list of elements as below. 

val element = new MyElement
//..... other prog logic..
elements.add(element)

将元素添加到列表时出现编译错误

我看到错误信息被列为 -

type mismatch; found : element.type (with underlying type    com.vo.MyElement) required: _$7 where type _$7 <: com.vo.Element

有没有办法解决这个问题?为什么 Scala 编译器无法破译 MyElement 确实是 Element 的子类并且可以添加到主列表中。

真的希望有人帮助我。我已经尝试了几种替代方案,但我无法让它发挥作用。我错过了什么还是我真的很愚蠢?

谢谢, 阿达什

【问题讨论】:

  • 这既不是 Java 也不是 Scala - MyElement extends Element 。同样地 - Class Container Element 是什么? container 是什么?这是什么 - case _ =&gt; ;
  • 你能解决这个问题并解释你想要做什么吗?
  • 我认为引起编译错误的语句是elements = new ArrayList[MyElement]()。 Java List 在泛型类型中是不变的:你怎么能将ArrayList&lt;MyElement&gt; 分配给List&lt;Element&gt;?还是我错过了什么?
  • @riccardo.cardin 这个问题有太多问题...我认为每一行都有问题。
  • @Adarsh 你确定你的 Java 代码部分没问题吗?

标签: java scala types


【解决方案1】:

如果你在 Java 中尝试过这个,你会遇到同样的问题(可能只有更有用的错误消息......)。

看看下面的代码,想想如果编译它会发生什么。

trait Element 
class MyElement extends Element
class MyOtherElement extends Element

import java.{ util => ju }
val myElements = new ju.ArrayList[MyElement]()
val elements: ju.List[_ <: Element] = myElements
elements.add(new MyOtherElement)
val myElement: MyElement = myElements.get(0)

顺便说一句,这与 Java vs Scala 无关:

import scala.collection.mutable.ListBuffer
val myElements = new ListBuffer[MyElement]()
val elements: ListBuffer[_ <: Element] = myElements
elements += new MyOtherElement
val myElement: MyElement = myElements(0)

原因是你在这里使用use-site variance,因为可变集合被定义为不变量。而且所有 Java 集合都是自动不变的,因为 Java 没有像 Scala 那样的声明站点变化的概念,而且它的集合无论如何都是可变的。

【讨论】:

  • 实际上,我在 java 中有这个工作,唯一应该在这里完成的更改是 val myElements = new ju.ArrayList[Element]()。即使在进行此更改时,我也无法将 Subclass 的元素添加到 Superclass 的数组列表中......
  • 是的,但重点是我编写的所有内容都可以编译,除了 elements.add(new MyOtherElement) add 部分,因为这会导致所有内容在运行时崩溃。
  • 当这些类是 Scala Hierarchy 的一部分时,它可以工作。但是我在 Java 类中有它们,这绝对没有问题。但不幸的是,我收到了这个错误。
  • 编译器无法知道elements中实例的实际类型是ju.ArrayList[Element]还是ju.LinkedList[MyElement],它只知道它是符合ju.List[_ &lt;: Element]的东西。不,它与 Java 类与 Scala 类无关。查看我的编辑。
  • 我知道这不是 Java vs Scala - 但重点是/是container.getElements() 返回List&lt;? extends NetworkElement&gt;。所以,我认为这就是问题所在。
【解决方案2】:

虽然,我不确定您的 Java 代码部分,但据我了解,您正在尝试执行以下操作,

  1. 您有一些Constainer 的实例为container
  2. 您想要获取该容器的元素并向其中添加新元素。

如果这是您想要做的,那么您可以执行以下操作,

val elements = {
  if (container.getElements() != null) {
    container.getElements()
  }
  else {
    val list: java.util.List[_ <: Element] = new java.util.ArrayList[MyElement]()
    list
  }
}


val element = new MyElement

elements.add(element)

【讨论】:

  • 这并不能解决我的问题。因为 java 库类有一个返回 List&lt;? extends Element&gt; elements 的 getter。需要将其更改为List&lt;? super Element&gt; elements
猜你喜欢
  • 2013-05-03
  • 2012-10-27
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多