Scala value classes are a sugary-sweet convenience, but they can introduce some low-level conflicts due to their compilation magic.
First, what are they? There's a thorough explanation in the Scala documentation, but in some useful terms: you use value classes to "wrap" a single primitive in an object. With that, you can add member methods as well as reap the benefits of the type system such as type-checking and polymorphism. How this differs from regular-old OO is that the Scala compiler will convert these types to the underlying primitive and will be allocated as such on the heap.
See these classes:
Here's how they are compiled:
The Scala compiler will ensure that MyClass2 always takes a ValueWrapper, but will convert it to an int in the bytecode. What does this mean? Usually, not much - it all works seamlessly under the hood while saving you memory. Until you need to use reflection. Which you never, ever use, right? Unless, of course, you are trying to get a reference to an Akka actor.
This code will compile:
But at runtime, Fail
[error] (run-main) java.lang.IllegalArgumentException: no matching constructor found on class MyActor for arguments [class ValueWrapper] java.lang.IllegalArgumentException: no matching constructor found on class MyActor for arguments [class ValueWrapper]
Which is frustrating, because there obviously is such a constructor; at compile time at least.
Somewhere down the chain, this is happening:
scala> classOf[MyActor].getConstructor(classOf[ValueWrapper]) java.lang.NoSuchMethodException: MyActor.<init>(ValueWrapper) at java.lang.Class.getConstructor0(Class.java:2810) at java.lang.Class.getConstructor(Class.java:1718)
There really is no solid workaround, but since you know all references of your value classes will be converted to their primitive types, you can just accept the primitive in the constructor and handle any conversions manually.