![](/img/trans.png)
[英]Java - Create new Instance using Reflection without knowing constructor params
[英]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.