I wrote the following Scala code:
import scala.collection.JavaConverters._
class MapConversion {
def fromScala[K, V](map: scala.collection.immutable.Map[K, V]): java.util.Map[K, V] = map.asJava
def toScala[K, V](map: java.util.Map[K, V]): scala.collection.mutable.Map[K, V] = map.asScala
}
and compiled it with
scala-cli compile --scala "2.12.11" .
(JavaConverters suggest Scala 2.12 or older).
Then I opened the resulting MapConversion.class in https://dmitriy-gulyaev.github.io/java-disassembler/ although I could just use javap as well.
Reading the bytecode suggest that the closest Java code would be something similar to:
class MapConversion {
<K, V> java.util.Map<>K, V> fromScala(
scala.collection.immutable.Map<K, V> map
) {
return
// get JavaConverters$ companion object instance
scala.collection.JavaConverters$.MODULE$
// use implicit conversion to wrap it in Decorators$AsJava
.mapAsJavaConverter(map)
// call asJava to convert the value
.asJava
}
<K, V> scala.collection.mutable.Map<K, V> toScala(
java.util.Map<K, V> map
) {
return
// get JavaConverters$ companion object instance
scala.collection.JavaConverters$.MODULE$
// use implicit conversion to wrap it in Decorators$AsScala
.mapAsScalaMapConverter(map)
// call asScala to convert the value
.asScala
}
}
(Disclaimer: I haven't tested it, and I don't intend to).
However, 99% of the time the requirement to "not use Scala language" would be hard to defend: it dismiss the right tool for the job (compiler), it requires reverse engendering which in turns requires the knowledge how JVM works, and it requires such reverse engineering every time any change is made. It also doesn't "save" the codebase from "Scala pollution" since apparently Scala standard library and code using it are already in the dependencies.
If the company as a whole don't want to deal with Scala, that's fine. But such issues can be much easier solved by:
- defining an interface:
interface JavaToScalaAdapters {
// ...
}
- implementing it in Scala as a top-level class with no constructor arguments, globals, etc
class JavaToScalaAdaptersImpl extends JavaToScalaAdapters {
// ...
}
- calling
new in Java to obtain this implementation and call it like any other Java code
JavaToScalaAdapters adapters = new JavaToScalaAdaptersImpl();
It could be a single artifact used in all companies Java projects, which rely on Scala even when they don't want to. Any other solution is wasting a lot of time and money. Even if it was a one-time workaround it is just faster to write it in Scala, compile, and throw .class file into resources directory in version control, than reverse engineer the code. The only justifiable cases where such reverse engineering would be justified would be learning or developing some low-level utilities.
javapwhat bytecode was generated and use that knowledge in Java. OTOH I think map converted expects an implicit evidenceA <:< (K, V), which in Java you'd have to instantiate and pass by hand. Here, additionally there might be the issue that Scala understands the idea of a type alias and Java not really, so you might have 2 different types, where in Scala there is only 1 type with 2 names. Perhaps casting the value returned byPredef.conformswould be enough.