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

Ben*_*ver 4 java reflection scala

我在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

我想要创建的对象实例的类在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)
}
Run Code Online (Sandbox Code Playgroud)

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

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))
}
Run Code Online (Sandbox Code Playgroud)

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

def this() = this(null.asInstanceOf[A])(null.asInstanceOf[Ordering[A]])
Run Code Online (Sandbox Code Playgroud)

另一种方法是子类化特定的具体值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]])
Run Code Online (Sandbox Code Playgroud)

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

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

Lex*_*Lex 7

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