簡體   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