2

Java

Set<Long> set = new HashSet<Long>();
set.add(100);
long x = 2;
foo(x, set);

Scala

def foo(a: Long, b: java.util.Set[Long])

Error:

could not parse error message:        
  required: long,Set<Object>    
  found: long,Set<Long>     
  reason: actual argument Set<Long> cannot be converted 
      to Set<Object> by method  invocation conversion

Then, I modified my Java code to resolve the compile-time error.

Set<Object> set = new HashSet<Object>();

However, the resolution of the compile-time error came at the expense of type safety. How can I properly resolve the above error?

EDIT

After @som-snytt resolved my issues here, I ran into this problem. I don't think it's the same question since , in my linked question, using, in Scala, foo(Long, java.util.Set[Long]) worked when calling (from Java) ScalaObject.foo(long, Set[Long])

4
  • 1
    This doesn't really answer your question but changing foo's signature to def foo(a: Long, b: java.util.Set[java.lang.Long]) should get rid of the compilation error. Commented Jan 31, 2014 at 15:59
  • foo(x: Long, set: java.util.Set[java.lang.Long] = { val y: scala.collection.immutable.Set[Long] = set.asScala.toSet is giving me: [INFO] found : scala.collection.immutable.Set[Any] [INFO] required: scala.collection.immutable.Set[Long] Commented Jan 31, 2014 at 16:15
  • That makes sense. I couldn't have predicted that without having seen foo's body. So you could either change all the Longs to java.lang.Long or import JavaConverters in foo's body as noted in the answer below. Commented Jan 31, 2014 at 16:21
  • 1
    [I appreciate your help - thank you. I didn't mean to post the response as criticism] Commented Jan 31, 2014 at 16:22

2 Answers 2

5

The types are wrong. The type of set in the Java code is java.util.Set[java.lang.Long], while the type in Scala is java.util.Set[scala.Long]. The scala.Long type is treated as the primitive long in Java, when not erased, and as java.lang.Object when erased (as you uncovered).

So either change Scala's type to Java's type to match. It's unfortunate that scala.Long erases to java.lang.Object, but necessary.

Sign up to request clarification or add additional context in comments.

4 Comments

is one approach better? My gut tells me that modifying my Java code to use Set<Object> is a poor choice compared to changing my Scala code's signature to foo(x: Long, set: java.util.Set[java.lang.Long], but I wasn't sure how to resolve the bug mentioned in my comment to manithetical. In REPL it works: scala> val x: java.util.Set[java.lang.Long] = new java.util.HashSet[java.lang.Long]() x: java.util.Set[Long] = [] || scala> x.add(100) res12: Boolean = true || scala> x.asScala.toSet res17: scala.collection.immutable.Set[Long] = Set(100)
[side-question, erase means how Java reads a type at run-time?] I've read your helpful post on type erasure (stackoverflow.com/questions/1094173/…) a few times, but don't fully understand it yet.
@KevinMeredith I prefer changing the type on the Scala method, though it could be inconvenient if you plan to do math on those longs. If they are identifiers of some kind, you should really look into creating a class for them -- it's the same cost as Long, and provides type safety.
@KevinMeredith As for "erasure", before Java 1.5, each type in the Java language had a direct correspondence in bytecode (which is what the JVM reads). When Java 1.5 introduced generics, instead of adding generics to bytecode they resorted to "erasing" the generics information from the types in the bytecode, and leaving the JVM unchanged. So, yes, you can think of it as how Java reads a type at run-time. Importantly, Java the Language You Write and Java the Language that Gets Executed (bytecode) are different languages, though both are called Java.
0

You probably want to import JavaConverters in this case.

import scala.collection.JavaConverters._
def foo(a: Long, b: java.util.Set[Long]) = ???

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.