繁体   English   中英

如何使用零参数构造函数创建具有通过Java反射绑定的上下文的Scala类的新实例?

[英]How to create new instance of Scala class with context bound via Java reflection using only zero argument constructor?

我在Scala中编写客户端代码,需要与Java中的框架进行交互。 该框架负责创建通过API指定的类的对象实例,它使用反射执行。 例如:

public class ReflectionUtil {

  public static <T> T newInstance(Class<T> aClass) {
    T result;
    try {
      Constructor<T> meth = aClass.getDeclaredConstructor(new Class[]{});
      meth.setAccessible(true);
      result = meth.newInstance();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return result;
  }
}

我想要创建的对象实例的类在Scala中实现,并在具有上下文绑定的类型上进行参数化。 例如:

class OrderedValue[A](var value: A)(implicit ord: Ordering[A]) {
  def get: A = value
  def set(x: A) = { value = x }
  def cmp(that: OrderedValue[A]): Int = ord.compare(this.value, that.value)
}

当我将此类传递给Java框架以构造新实例时,我遇到了一个问题,因为框架假设该类将具有零参数构造函数。 例如,以下代码将导致newInstance中的NoSuchMethodException

def main(args: Array[String]) {

  val a: OrderedValue[Int] = ReflectionUtil.newInstance(classOf[OrderedValue[Int]])
  val b: OrderedValue[Int] = ReflectionUtil.newInstance(classOf[OrderedValue[Int]])

  a.set(3)
  b.set(5)

  println(a.cmp(b))
}

尝试解决此问题的方法是向OrderedValue添加零参数构造函数,但隐式参数ord没有合理的值。 将其设置为null将导致cmp中出现NullPointerException

def this() = this(null.asInstanceOf[A])(null.asInstanceOf[Ordering[A]])

另一种方法是子类化OrderedValue的特定具体值。 例如:

class OrderedIntValue(val v: Int) extends OrderedValue[Int](v) {
  def this() = this(null.asInstanceOf[Int])
}

val a: OrderedValue[Int] = ReflectionUtil.newInstance(classOf[OrderedValue[Int]])

这将起作用但并不理想,因为了解OrderedValue的具体类型并不总是方便或可能。 例如, newInstance可以在范围内调用,该范围也在类型上进行参数化(即我们不知道它特别是Int )。

所以我的问题是:鉴于上下文边界(即类型类)是Scala中非常有用且现在常用的特性,并且考虑到我无法更改我正在连接的Java框架的内部,有人遇到过或者开发出一种方法,可以使这一切工作?

Scala编译器在编译时填充隐式参数。 如果要使用反射实例化类,则必须手动指定这些参数。 没有办法绕过它。 所以你可以有上下文边界或无参数构造函数。

我发现从Java调用Scala代码的最简单方法是使用Scala等效的POJO编写一个中间Scala层。 没有隐含,没有签名闭包,没有Companion对象,没有复杂的类型推断等等(当然,你可以在内部使用它们)。 我还尝试用java.util集合替换签名中的大多数scala集合类型。

是的,它很丑陋,乏味且不够灵活,但至少它从Java方面消除了很多语法噩梦。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM