使用java泛型从java调用重载scala case apply



有几个方法我需要用Java写,大部分系统是用scala写的。除了一种情况,互操作性不是什么大问题。

我有一个java方法,它在调用一个方法时使用泛型T,传递进来的泛型实际上是一个scala case类。我面临的挑战是从java代码中调用case类的重载apply方法。它无法解析方法应用。我已经尝试了T的扩展定义的几种变体,但似乎没有一个能解决问题。

有什么建议吗?下面是到目前为止的代码的简化版本:

Java(方法)

public <T> Option<T> getResult(String name) {
    Iterator<Item> items = repo.results(name).iterator();
    if (items.hasNext()) {
        T model = T.apply(items.next());  // ?? how to call overloaded case class apply method
        return new Some<>(model);
    }
    return scala.Option$.MODULE$.apply(null);
}

Scala case类(带有重载的apply方法),许多可能的case类之一。

case class Person (id: Int, name: String)
object Person {
  def apply(item: Item) = toObject(item)
  def toObject(item: Item): Person = {
    Person(
      item.getProperty[Int]("id"),
      item.getProperty("name")
    )
  }
}

你的代码有两个问题:

  1. Java泛型在运行时被擦除,因此为了做T.apply之类的事情,您需要T的实例,因此您的方法看起来像:

    public <T> Option<T> getResult(String name, T t)

  2. 您需要定义apply方法的上界,以确保您可以在T上调用该方法。但是,scala在伴生对象中声明了这一点,伴生对象是与其伴生类分开的一个类。并且没有任何超类来描述它们应该实现哪些apply方法。

我唯一能想到的是,如果你知道apply方法只有一个参数:

public <T> Option<T> getResult(String name, Function1<Item, T> companion){ // this is extended by companion objects of case class that take only 1 parameter
 ... 
  T model = companion.apply(items.next());
 ...
}
使用这种方法,您可以像这样调用方法:
 getResult("name", Person$.MODULE$)  //pass the companion object as a factory 

最新更新