How to let Java programs within a Scala project invoke Scala functions or vice versa?

657 views
Skip to first unread message

Allen Nie

unread,
Jul 27, 2014, 1:24:04 PM7/27/14
to scala...@googlegroups.com
I know maybe this question was asked before, but I couldn't find it. Scala projects like Play Framework, Akka, and Spark (Apache Spark) all claimed that they "have APIs for both Java and Scala". You can use the library in either of two languages. I am very curious how is that accomplished?

Second of all, a standard SBT project may have a following folder tree:

/src
/src/main
/src/main/java
/src/main/resources/
/src/main/scala

Can the programs saved in java invoke methods from the programs in Scala? Can it happen vice versa (Scala program invokes those Java methods)?

Oliver Ruebenacker

unread,
Jul 27, 2014, 1:50:23 PM7/27/14
to Allen Nie, scala-user

     Hello,

  Yes, Java can call Scala methods and vice versa. So you could have one API, implemented in either Java or Scala, and use it from either Scala or Java.

  In most cases, this is simple and straight-forward.

  There are cases where is gets more complicated, for example, when you use in Scala an identifier that is not a valid Java identifier, but you want to call it from Java. For example, + operator in Scala will be called something like $plus$ when seen from Java.

     Best,
     Oliver



--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Be always grateful, but never satisfied.

Allen Nie

unread,
Jul 27, 2014, 1:56:41 PM7/27/14
to scala...@googlegroups.com, aimi...@gmail.com
Thank you for responding :) 

Theoretically I understand what you said. I can easily call a Java method if I want to use a Java Library (adding it as a jar dependency). However, imagine this scenario: I'm writing a web routing application in Spray (Scala), and the web routing application needs to finally call the main application, which is written in Java. Can this be somehow arranged? Do I have to compile/assemble those Java code and add them as jar files, or can they stay as normal Java files in that src/main/java folder, and my IDEs can figure it out my method calling?

There isn't much written about this topic, but major frameworks/libraries all have this amazing interoperability. 

Oliver Ruebenacker

unread,
Jul 27, 2014, 2:09:49 PM7/27/14
to Allen Nie, scala-user

     Hello,

  I don't know Spray, but you see, all you source files, whether they are Java or Scala, will be compiled into class files. It doesn't matter which source directory they came from as long as the class files end up in the right place.

  My understanding is that writing a Scala object that extends App is equivalent with writing a Java class that contains a main method, that is, both will be compiled into a class file that can be executed.

     Best,
     Oliver

Antoine Gourlay

unread,
Jul 27, 2014, 2:22:05 PM7/27/14
to Oliver Ruebenacker, Allen Nie, scala-user
If you are asking how this is accomplished in practice (mixed scala/java sources with mutual dependencies in the same project): it works by having the scala compiler parse both scala *and* java sources. So you have:

 1. `scalac` is invoked with the scala and java sources. The java sources are parsed to extract the API that scala sources can use, and then classfiles for the scala sources are emitted,
 2. `javac` is invoked on the java sources, with the scala classfiles on the classpath.

This is the standard "mixed" mode [used by sbt][1], for example.

[1]: http://www.scala-sbt.org/0.13/docs/Java-Sources.html

Allen Nie

unread,
Jul 27, 2014, 3:26:44 PM7/27/14
to scala...@googlegroups.com, cur...@gmail.com, aimi...@gmail.com
This is very helpful and is what I'm looking for. 

Suppose I have these two paths under src/main:

java/
com.xxx.somePackage.oneClass (in this class we have multiple methods such as "getOneFile()")

scala/
com.xxx.api.oneObject (suppose one method inside: "saveOneFile()")

So inside com.xxx.api.oneObject I can write:

object oneObject {
  import com.xxx.somePackage.oneClass._

  val newJavaClass = new oneClass()
  newJavaClass.getOneFile()
}

And on the Java program located com.xxx.somePackage.oneClass, I can write:

import com.xxx.api.oneObject
class oneClass {
   oneObject.saveOneFile(); //suppose I'm following Java/Scala interoperability rules
}

SBT will compile them successfully under mixed mode, correct? (Assuming there isn't any circular dependency)

My only question left is: am I importing Java into Scala or Scala into Java the right way (under the right class path)? Will my IDE (IntelliJ) understand this type of reference?

Antoine Gourlay

unread,
Jul 28, 2014, 8:14:55 AM7/28/14
to Allen Nie, scala-user, Oliver Ruebenacker

SBT will compile them successfully under mixed mode, correct? (Assuming there isn't any circular dependency)

Yes.

My only question left is: am I importing Java into Scala or Scala into Java the right way (under the right class path)? Will my IDE (IntelliJ) understand this type of reference?

Yes, you use the standard import xxx clause on both sides. IntelliJ and Scala IDE are both capable of understanding mixed code bases, although IntelliJ may need some more configuration to make it work, depending on your setup.

Reply all
Reply to author
Forward
0 new messages