[英]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.