I’d like to make an appeal for package-private visibility to be added to Kotlin/JVM, perhaps via an annotation.
Me and my team have been using Kotlin for several years now. Lack of package-private is probably one of the top pain points for us and I predict it will get worse in future. The problem is that the JVM does not understand internal. It’s a concept that exists only in the Kotlin language frontend. Whenever you have mismatches between language and VM concepts you can hit problems
The problems are like this:
- Marking a constructor as internal is useless for us because we have Java users who use our API. Internal c’tors show up as ordinary public c’tors when used from Java. There is no hint anywhere whilst coding that you should not use them. So of course, there is a risk that people do. As a consequence we feel we have to preserve all c’tors from the past in our library API/ABI, which means lots of
@JvmOverloadsbut that in turn creates ugly APIs and JavaDocs, and can be confusing because it often implies you can create an object that only really has meaning when created by our own code.
- As is sometimes the case for Java programs, we support loading plugins (“apps”) into our main server program, and we’d like to use JVM sandboxing in future. With JVM sandboxing or Jigsaw properly activated you cannot define classes inside other packages, so you can build secure sandboxes. But Kotlin’s lack of support for package-private means that “internal” doesn’t actually mean anything to the JVM and thus can’t act as a security boundary, at least not without a lot more work.
- We have relatively large modules because modules represent both functionality and API stability boundaries. So marking something as “internal” still exposes it to a large quantity of code that often isn’t really justified.
- Internal works via name mangling and has a history of weird bugs caused by IntelliJ and Gradle builds not agreeing on the mangling scheme to use.
We really enjoy using Kotlin on the Corda project and there are now hundreds of app developers building apps on the platform, many of them using Kotlin too. But what we really need is the original vision of Kotlin as a better Java, rather than Kotlin as a new multi-platform language that happens to compile to bytecode in some use cases. The places that cause us the most pain for creating and evolving a large API are almost always the places where Kotlin’s semantics have deviated from Java’s in ways that cause the Java tooling to barf.