6

The following Scala example defines a class inside a package object:

package com.mycompany

package object test {
  class MyTest {
    def foo(): Int = {
      42
    }
  }
}

The following three classes are generated:

com/mycompany/test/package.class
com/mycompany/test/package$.class
com/mycompany/test/package$MyTest.class

The problem arises when trying to use the MyTest class from Java. I think that since package$MyTest contains a $ in the name, Java is not acknowledging its existence. Nevertheless, the package$ class is accessible.

Running javap on package$MyTest.class returns:

Compiled from "Test.scala"
public class com.mycompany.test.package$MyTest {
  public int foo();
  public com.mycompany.test.package$MyTest();
}

I've tried accessing the class using Eclipse, Intellij and Netbeans, without success. Is it possible to use Scala classes defined in package objects from Java?

2 Answers 2

5

Defining a class inside the package object test is currently not implemented the same way as defining it inside the package test, although it probably should (this is being tracked as SI-4344).

Because of that, it is usually good practice to place into the package object only definitions that cannot be top level, like vals, defs, etc. (this is the whole point of package objects after all), and leave class/object definitions into a normal package definition:

package com.mycompany

package object test {
  // vals, defs, vars, etc.
  val foobar = 42
}

package test {
  // classes, objects, traits, etc.
  class MyTest {
    def foo(): Int = {
      42
    }
  }
}

This will produce a normal MyTest class, easily accessible from Java:

com/mycompany/test/MyTest.class
com/mycompany/test/package.class
com/mycompany/test/package$.class
Sign up to request clarification or add additional context in comments.

1 Comment

This is useful when I am writing the package class, but not when I am using a third party library.
3

package$MyTest follows JVM convention for nested classes, so it would be visible as package.MyTest... except this isn't a legal name in Java. Which means it can't be accessed.

5 Comments

So .. then what .. I have types in the package object that are used ubiquitously in the classes in the package. Then .. for all of the (hundred or so) classes / traits etc we need to do an import SomeContainer._ where SomeContainer is a java-friendly alternative to the package object?
You can't use types in Java anyway.
I discovered that little "treat" (no types in java ..) soon after seeing this answer. It seems that using scala framework within java is basically a non-starter ;( . I am creating a separate adapter to allow a subset of the scala functionality to be accessible through java. This places a firm limitation on the ability to use scala : it can not be considered general purpose within java / scala teams : only java -> scala really works beyond simple things.
Using a Scala framework which isn't intended for it can be, yes. Note that you can use full power of Scala for the implementation, the limitation is only on the API. But you'll run into the same problem for any similar pair of languages, e.g. C and C++.
Not able to use types or trait's .. that's almost no longer scala .. We are keeping scala separate from java handling since too many core scala features are incompatible.

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.