{"id":16505379,"url":"https://github.com/deanwampler/scalajavainterop","last_synced_at":"2026-06-05T22:31:20.383Z","repository":{"id":977563,"uuid":"777602","full_name":"deanwampler/ScalaJavaInterop","owner":"deanwampler","description":"A simple \"lightning talk\" about Scala-Java Interoperability for the Chicago Scala user group","archived":false,"fork":false,"pushed_at":"2010-07-16T14:38:02.000Z","size":924,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-23T12:29:53.568Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://meetup.com/chicagoscala","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deanwampler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-07-15T21:22:08.000Z","updated_at":"2025-02-06T13:41:31.000Z","dependencies_parsed_at":"2022-07-05T22:30:46.807Z","dependency_job_id":null,"html_url":"https://github.com/deanwampler/ScalaJavaInterop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deanwampler%2FScalaJavaInterop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deanwampler%2FScalaJavaInterop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deanwampler%2FScalaJavaInterop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deanwampler%2FScalaJavaInterop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deanwampler","download_url":"https://codeload.github.com/deanwampler/ScalaJavaInterop/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241444060,"owners_count":19963752,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T15:11:01.726Z","updated_at":"2026-06-05T22:31:20.378Z","avatar_url":"https://github.com/deanwampler.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scala-Java Interoperability\n\nLightning talk at the July 15th, 2010 Chicago-Area Scala Enthusiasts meeting.\n\nDean Wampler\n\n[GitHub](http://github.com/deanwampler/ScalaJavaInterop)\n\n# Introduction\n\nThis talk explores how Scala writes valid byte code and what that means for interoperation with Java. I compiled the code with `sbt` and then used `javap` to examine the byte code signatures.\n\n## References\n\nSee the following for more details:\n\n* **Programming Scala**, Chapter 14:\n * [Java Interoperability](http://programming-scala.labs.oreilly.com/ch14.html#JavaInterop)\n * [Java Interoperability](http://programming-scala.labs.oreilly.com/ch14.html#JavaLibraryInterop)\n* Daniel Spiewak's post on [Interop Between Java and Scala](http://www.codecommit.com/blog/java/interop-between-java-and-scala)\n\nThe notes that follow largely follow the outline of Daniel's blog post.\n\n## Using the Examples\n\nThe code is built using `sbt`. (The `# foo` are comments and `$` and `\u003e` are shell and `sbt` prompts, respectively.\n\n    $ ./sbt       # invoke the provided sbt script\n    \u003e update      # Upate jars\n    \u003e compile     # build the code.\n    \n(There are no tests provided.) The class files are written to the `target/scala_2.8.0.RC7/classes/`.\n\nUse `javap`, part of the JDK distribution to see how the names, method signatures, etc. are encoded at the byte code level; how they appear to `javac` or `java`. Note the space before the package name `interop`:\n\n    javap -classpath target/scala_2.8.0.RC7/classes/ interop.JListMapper\n    javap -classpath target/scala_2.8.0.RC7/classes/ 'interop.JListMapper$' \n\nNote that you need to escape the '$' in the latter example. Otherwise, it is interpreted as the start of a shell variable expansion. I just put the object name in single quotes.\n\nUse `scalap`, part of the Scala distribution to see how the names, method signatures, etc. are reinterpreted as Scala. \n\n  scalap -classpath target/scala_2.8.0.RC7/classes/ interop.JListMapper\n  scalap -classpath target/scala_2.8.0.RC7/classes/ 'interop.JListMapper$' \n\nThe signatures will look pretty much the same as the original source. Use the open-source tool [jad](http://varaneckas.com/jad) to attempt to reverse engineer the byte code back to working Java. It doesn't always work completely. I'm not sure why, but it might make assumptions that `javac` wrote the byte code and hence not properly understand idiosyncrasies of `scalac` output.\n\nThere is one executable in the code.\n\n    scala -cp target/scala_2.8.0.RC7/classes/ interop.JFunctionMain foo bar baz\n    \nI'll discuss these examples in the following sections.\n\n# Character Encoding\n\nScala allows a wider variety of characters for type and method names than Java's `[_a-zA-Z][_a-zA-Z0-9]*`. So, Scala encodes the extra characters thusly:\n\n    trait AllOpChars { \n      def == : Unit   // $eq$eq \n      def \u003e  : Unit   // $greater \n      def \u003c  : Unit   // $less \n      def +  : Unit   // $plus \n      def -  : Unit   // $minus \n      def *  : Unit   // $times \n      def /  : Unit   // $div \n      def \\  : Unit   // $bslash \n      def |  : Unit   // $bar \n      def !  : Unit   // $bang \n      def ?  : Unit   // $qmark \n      def :: : Unit   // $colon$colon \n      def %  : Unit   // $percent \n      def ^  : Unit   // $up \n      def \u0026  : Unit   // $amp \n      def @@ : Unit   // $at$at \n      def ## : Unit   // $hash$hash \n      def ~  : Unit   // $tilde \n    }\n  \nThere appear to be some additional coding conventions for \"specialized\" type instantiations, e.g., `List[Double]` for `List`. I couldn't find any documentation on these. Feedback welcome!\n\nYou can see an example of this encoding when you compile `PersonTrait.scala` and run `javap` on it. Look for the `name_$eq` method. This is the compiler-generated setter method `name_=` that allows you to write, e.g.,\n\n    myperson.name = \"Bubba\"\n\n# Classes\n\nClasses declared in Scala vs. Java have almost identical byte code. The Scala generated code will implement a `ScalaObject` interface.\n\nNote that my book and Daniel's blog post refer to an internal `$tag` method required by the `ScalaObject` interface. This method was removed in Scala 2.8.\n\n# Traits vs. Interfaces\n\nTraits with no defined methods or fields are identical to interfaces and can be used interchangeably between Java and Scala. For example, see the `AbstractPerson` in `PersonTrait.scala`.\n\nTraits with methods lead to the generation of a companion `Foo$class` class, which holds the method implementations. For example, see the `Person` in `PersonTrait.scala`. Two class files are generated by `scalac`, `Person.class` for the \"interface portion\" and a corresponding `Person$class.class` file that contains the method bodies.\n\nSee how these are used in Scala and Java in the `Employee.scala` and `Employee.java` files, respectively.\n\n# Generics\n\nScala type parameters are a superset of Java generics, _e.g.,_ covariant and contravariant subtyping.\n\n    trait Function2[-A1, -A2, +R] {\n      def apply(a1: A1, a2: A2): R\n    }\n    \nJava only lets you specify covariant and contravariant behavior at the _call_ site, not the _definition_ site. Scala gets away with this and other type system enhancements because of type erasure! That maligned feature lets Scala \"sneak in\" the improved behavior.\n\n# \"Operators\" Are Methods\n\nWhen you write\n\n    val list = 1 :: 2 :: 3 :: Nil\n    \nYou are actually just calling methods on `List`.\n\n    abstract class List[+A] {\n      def ::[B \u003e: A](e: B) = ...\n      ...\n    }\n\n# Higher-Order Functions in Java\n\nFunctions in Scala are objects, e.g., a one-argument function is the following.\n\n    trait Function1[-T, +R] {\n      def apply (t: T): R\n      \n      def toString = ...\n      def compose[A](g: A =\u003e T): A =\u003e R = ...\n      def andThen[A](g: R =\u003e A): T =\u003e A = ...\n    }\n    \nYou can use these in Java! However there's a catch. In 2.7.7, you had to define `apply` and the internal method `$tag`, something like this. \n\n  Function1\u003cString,String\u003e toUpper = \n    new Function1\u003cString,String\u003e() {\n      public String apply(String s) {\n        return s.toUpperCase();\n      }\n      public int $tag() { return 0; }\n    };\n\nIn 2.8.0, `$tag` is no longer required, but it also appears that the new `@specialized` annotations cause problems when instantiating anonymous subclasses of the `FunctionN` traits in Java code. You get errors for undefined `andThen` methods, e.g., for type `R` = `Double`.\n\nTo work around this, create a concrete subclass of `Function1[String,String]` in Scala code with a default implementation of the `apply` method. Then, in the Java code, create a subclass that overrides `apply` to do the actual work desired. An alternative is to have the default `apply` call an abstract helper method, say `doApply`, then define `doApply` in your Java code subclass (i.e., use the Template Method pattern). \n\nFor an example, see `JListMapper` and `JFunctionMain`.\n\n# Interoperation with Java Libraries.\n\nThe most important issue you'll encounter, beyond what we've discussed so far, is the fact that some Java libraries, _e.g.,_ the Spring Framework and most IDEs, expect objects to follow JavaBeans conventions:\n\n    public class Person {\n      public Person(...) {...}\n      public String getName() {...};\n      public void   setName(String s) {...};\n      // etc.\n    }\n    \nOften these tools use reflection to locate \"bean properties\" this way. In contrast, consider the corresponding Scala class.\n\n    class Person(var name: String, ...)\n    \nIt uses `name` for the getter and `name_=` for the setter, of course. If you need bean methods, use the `@scala.reflect.BeanProperty` on each field, or use `@scala.reflect.BeanInfo` on the class to affect all fields. \n\nSee the `PersonBean` example in `PersonTrait.scala` and use `javap` on the generated class files, `PersonBean.class` and `PersonBean$class.class`. As written, `getName` and `setName` methods are generated. Try this experiment, remove the assignment for `name`, so that it is pure abstract. Compile again and look at the class files with `javap`. You'll see that just the getter `getName` is defined, not the setter `setName`, even though we declared it as a `var`. I don't know why...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeanwampler%2Fscalajavainterop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeanwampler%2Fscalajavainterop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeanwampler%2Fscalajavainterop/lists"}