Well, public is technically module-private for any non-exported package. /Michael ________________________________ From: jigsaw-dev <jigsaw-dev-boun...@openjdk.java.net> on behalf of Mike Hearn <m...@plan99.net> Sent: 24 September 2019 18:24 To: jigsaw-dev@openjdk.java.net <jigsaw-dev@openjdk.java.net> Subject: Could we get module-private visibility?
Hello, Often you want a method or constructor to be private to your module. The closest approximation for this today is package-private, but this isn't an ideal match. Kotlin has the "internal" modifier, which makes the modified element be visible only inside a module. This is simple and often what you want if you have small modules (which Jigsaw makes much more practical), however, the JVM doesn't understand it so it's not enforced for other languages or in reflection/sandboxing. Using package-private correctly can be tricky. Using Kotlin's notion of internal is even worse because it gets mapped to public, so in effect the entire Java ecosystem ignores it. I think the underlying issue is that packages do a lot of work. They provide at minimum: 1. Better organisation of an API in JavaDocs, so types can be given descriptions and broken up to make exploration easier for users. 2. Organisation of a codebase for developers who work on it, to stop their IDEs being overwhelmed with giant lists of classes. 3. An abstraction boundary, so implementation details can be hidden from the API user. 4. A sandboxing boundary, so capabilities can be implemented more easily. 5. A VCS access control boundary, because they map to directories and many version control systems let developers own directories. 6. An IDE autocomplete boundary, so you can glob import and get better auto completion. So it's not surprising that they get used in various different ways. The JDK is filled with weird "secrets" classes that exist mostly because of mismatches between what level of visibility is needed vs provided. Nestmates have helped mop up some tech debt in this area, but what's offered to users hasn't changed much. Writing code for sandboxed usage is hard when you simultaneously want e.g. one package per backend of your API but also need those backends to access internal methods in top-level generic API classes. Calls cross package boundaries so package-private isn't quite right. An internal modifier like Kotlin's but supported by the JVM would help a lot for crafting good APIs. Alternatively, an interesting move might be to do invokedynamic but in reverse: allow methods/c'tors/fields in class files to declare other methods as 'guards' which decide at runtime if a link should be allowed or not. Then languages can implement whatever visibility rules they want in their standard library, and more of the JVM's linker logic can be moved into Java itself.