Make a Java class package private for Scala


#1

Hello,

I have the following Java class, usage is irrelevant:

public abstract class ADT {
  public final int id;
  public ADT(int id) { this.id = id; }
}

Given that Java package private classes are not visible in sub-packages (for some reason that I don’t understand), I want to create the equivalent of this:

package myPackage

private[myPackage] abstract class ADT(val id: Int)

Is there any annotation that I can add to my Java class in order to achieve this? How does the Scala compiler encode it in the bytecode?


#2

I think that information is part of the payload of a ScalaSignature or ScalaLongSignature annotation, which contains all Scala specific type/symbol information in serialized form. So I think you’ll have to fake the entire contents of that annotation to make the compiler believe it’s a Scala package private class.


#3

Package namespace in the JVM is flat, not hierarchical. Any two packages are separate and cannot access the other’s package-private members.
My guess would be that scalac generates package private members in Scala sense as public in the class files and enforces access restrictions only at the source level.


#4

Package-private classes are public as far as the JVM is concerned.

The Java convention is usually to create an “internal” package in the hierarchy, e.g. “com.example.foobar.internal.ADT”. I’d suggest doing that and adding a comment to the javadoc indicating that it’s internal API. You can also use an annotation like Akka does: https://doc.akka.io/japi/akka/current/akka/annotation/InternalApi.html.