有几个方法我需要用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")
)
}
}
你的代码有两个问题:
-
Java泛型在运行时被擦除,因此为了做
T.apply
之类的事情,您需要T
的实例,因此您的方法看起来像:public <T> Option<T> getResult(String name, T t)
-
您需要定义
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