The "exposes" Keyword in Java

Don't worry. You have not been sleeping under a rock for the past few years. There is no such keyword in Java. It's just something I wish for Christmas.

It's great that Java modules finally allow us to truly seal off our carefully crafted API surfaces, without clients being able to crack them open anyway using reflection. If a module does not "open" a package to the outside world, there is no way you can access its private and package-private members. No more reflectively setting a private field's accessible flag to true and force it to yield or change its value.

Unfortunately, you can also no longer use reflection to dynamically read/write public fields or execute public methods. It does not matter whether the fields and methods hail from an exported or non-exported package. As long as the module does not also open the package, any reflection is off limits. In fact you no longer have any self-contained (purely programmatic) way of knowing what public fields and methods there are in the first place. That, after all, requires calls to methods like Class.getFields() and Class.getMethods(). That's reflection and hence forbidden.

If, on the hand, you do open the package, it abruptly becomes the free-for-all-do-whatever-you-like playground again that it was before Java modules came along. 

This choice is too extreme, I think. We need an in-between option that allows us to ask what public fields and methods there are, but nothing else — without us immediately transitioning into Greek deities that than can wreak havoc as we please with the internals of the class. Dynamically reading/writing public fields is still forbidden with this option, as is dynamically executing public methods. This option would be enabled via the "exposes" keyword (or whatever other keyword the Java language architects prefer instead). Thus, a module can export, expose or open a package.

Why would you want to know what public fields and methods a class has if you can't do anything with that knowledge? But you can! Just not via reflection. Slightly predating Java modules are method handles and the java.lang.invoke package (they were introduced in Java 7). Interestingly, while method handles also enable dynamic method invocation, using method handles to dynamically execute a public method does not require that the package containing the method is open. Just exporting the package gives clients enough privilege to request a MethodHandle for a public method or a VarHandle for a public field.

Thus, if only  the JVM could let us know just what the public fields and methods are, we could dynamically read/write/execute them, while the module that submits itself to this can rest assured that we won't do, and won't be able to do the invasive things that reflection allows us to do.

Comments

Popular posts from this blog

LinkedList - Lost Opportunity?

Type Maps