2

I have a scala project that is generating a jar. I'm trying to use the jar in a Java project. The weird thing is the method signatures are losing generic type information when they are compiled to .class files.

def foo(x:List[Long]) = ...  

generates a method with
Lscala/collection/immutable/List<Ljava/lang/Object;>
in its .class file.

It's the same with

def foo(x:java.util.List[Long]) = ...  

the .class file says the method signature is
Ljava/util/List<Ljava/lang/Object;>

The real problem is that when I use this jar in a Java project I have to use List<Object> instead of List<Long> like I want. Sure I can cast it, but I would rather not have to. Any ideas?

I am using scala version 2.11.7

Odomontois
  • 15,918
  • 2
  • 36
  • 71
Tim
  • 1,013
  • 1
  • 10
  • 16

1 Answers1

5

If you want your method to be callable from Java in the way that you want, you must declare it to take a List[java.lang.Long].

Why? Well, scala.Long is the equivalent of Java's long, not Java's java.lang.Long. And in the Java type system, type parameters may not refer to primitive types, only reference types. So Scala cannot emit the "correct" signature and is forced to fall back to java.lang.Object.

(In very old versions of Scala, it used to fall back to java.lang.Long instead, but unfortunately that isn't actually a 100% correct solution and caused a bunch of interop problems. See https://issues.scala-lang.org/browse/SI-4214 for gory details. Unfortunately, I don't know of a more concise writeup. This comes up fairly often, so if there is such a writeup, I would like to know about it.)

Seth Tisue
  • 29,985
  • 11
  • 82
  • 149
  • Oh of course! Thank you! – Tim Oct 20 '15 at 18:19
  • It is a good idea to consider using `Array[Long]` as this will be translated to `long[]` in Java. Surely not always possible, but it makes both Java and Scala sides looking good and without ugly signatures – Archeg Oct 20 '15 at 19:14