How to create a new instance of the Scala class with context binding through Java reflection using only the null argument constructor?

I am writing client code in Scala that should interact with the framework in Java. The structure is responsible for instantiating the objects of the classes specified through the API, which it uses with reflection. For instance:

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; } } 

The instance classes of the objects I want to create are implemented in Scala and parameterized on a type that has a context associated with it. For instance:

 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) } 

I encounter a problem when I pass this class to the Java environment to create new instances, as the framework makes the assumption that the class will have a constructor with a null argument. For example, the following code will NoSuchMethodException from inside 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)) } 

An attempt to solve this problem is to add a constructor with a null argument to the OrderedValue , however there is no reasonable value for the implicit ord parameter. Setting null will result in a NullPointerException inside cmp :

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

Another approach is to subclass a specific concrete value of OrderedValue . For instance:

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

This will work, but not ideal, since it is not always convenient or possible to find out the specific type of OrderedValue . For example, newInstance can be called within the scope, which is also parameterized by type (i.e., we don’t know what it is specifically Int ).

So my question is: given that context boundaries (i.e. type classes) are a very useful and now widely used function inside Scala, and given that I cannot change the internals of the Java structure I'm interacting with, did anyone come across or developed an approach that can make it all work?

+4
source share
2 answers

Implicit arguments are populated by the Scala compiler at compile time. If you want to instantiate classes using reflection, you will have to specify these arguments manually. There is no way around. Thus, you can have either contextual boundaries or constructors with no arguments.

+7
source

I found that the easiest way to call Scala code from Java is to write a Scala middleware with the Scala POJO equivalent. No implications, no closures in signatures, no Companion objects, no complex type inference, etc. (Of course, you can use them internally). I am also trying to replace most Scala Collections types in signatures using java.util Collections.

Yes, it is ugly, tedious and not very flexible, but at least it removes a lot of syntax nightmare from Java.

+3
source

All Articles