Proposal: Move the `Module` and `Layer` classes from `java.lang.reflect` to `java.lang`
mark.reinhold at oracle.com
mark.reinhold at oracle.com
Mon Mar 27 15:10:42 UTC 2017
(I'm proposing this API change via a new issue in order to make sure
that everyone is aware of it. Please let me know ASAP if you have any
concerns; I'd like to merge it into an update of the Public Review
draft.)
Issue summary
-------------
#MoveModuleAndLayerClasses -- Move the `Module` and `Layer` classes,
and a related exception class, from the `java.lang.reflect` package up
into the `java.lang` package. This will improve conceptual clarity, be
consistent with the past, and leave room for the future. [1]
Proposal
--------
Move and rename these classes as follows:
java.lang.reflect.Module -> java.lang.Module
java.lang.reflect.Layer -> java.lang.ModuleLayer
java.lang.reflect.LayerInstantiationException
-> java.lang.ModuleLayerInstantiationException
The `Layer` class is renamed to `ModuleLayer` so that it's easy for
readers to skip over that class by name rather than have to read its
Javadoc in order to learn that it's not what they're looking for.
The related exception is renamed to match. (The `Module` class is
not renamed, about which more below.)
Motivation
----------
Experience shows that the best high-level shape for a non-trivial API is
often not apparent until it's nearly finished. Looking at the totality
of classes and interfaces in the draft specification [2] and considering
the history and potential future of the platform leads to several reasons
for this proposed change.
- For explanatory purposes there is a very useful and pleasant
high-level conceptual analogy:
class : class loader :: module : module layer
That is, classes are instantiated via class loaders, and modules are
instantiated via layers. The types corresponding to these concepts
should all be in the same package.
- Existing constructs with keyword declarations in the language already
have corresponding types in the `java.lang` package: `Class` for
`class` and `interface`, `Package` for `package`, and `Enum` for
`enum`. Placing `Module` in the same package is consistent with
these past choices.
- The concepts of modules and layers will be with us for a very long
time, and are just as fundamental as those of classes and class
loaders. The core reflection API in `java.lang.reflect` will be
with us for a very long time too but it's not as fundamental, and it
stands a good chance of being de-emphasized over time as alternatives
are developed (e.g., Maurizio Cimadamore's mirror proposal [3]).
- Long after `Class` was introduced we extended the language with the
concept of class literals (e.g., `Object.class`). Peering into the
future, at some point we may want to extend the language to allow
modules to be mentioned outside of module declarations, and in ways
that relate language-level expressions to run-time `Module` objects.
It would be unfortunate if such constructs had to be specified in the
JLS to refer to a `Module` type in a legacy, de-emphasized
`java.lang.reflect` package.
Impact
------
This is a cosmetic change. No functionality will be added or removed.
This change is not, however, source-compatible relative to Java SE 8. It
adds new types to the `java.lang` package, which is implicitly imported
on demand (i.e., `import java.lang.*`). If code in an existing source
file imports some other package on demand, and that package declares a
`Module` type, and the existing code refers to that type, then the file
will not compile without change. This could affect, among others, users
of the popular Guice framework, which declares its own `Module` type [4].
The impact of moving these three types from `java.lang.reflect` up into
`java.lang` is ameliorated by two factors:
- A very common best practice is to use precise, type-specific `import`
statements (e.g., `import com.google.inject.Module`) rather than
import-on-demand wildcards (e.g., `import com.google.inject.*`).
Code that follows this practice, which is well-supported by all the
major IDEs, will compile without error [5].
- If you declare a `Module` type in your own package then other code
in your package that refers to that type will not be affected by the
existence of `java.lang.Module`. That's because an unqualified type
name in source code resolves to a type in the same package in
preference to a type in an import-on-demand package.
It may sometimes be necessary to add or adjust `import` statements in
order to compile existing source code for Java SE 9 but, unlike some
other kinds of changes required for migration, these kinds of changes
will compile on earlier releases.
Source compatibility from release to release is, in general, highly
desirable. Unlike binary or behavioral compatibility, however, it has
never been a total commitment of the Java Platform. Over the years we
have from time to time broken it in order to move forward, and this is
one of those times.
[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#MoveModuleAndLayerClasses
[2] http://cr.openjdk.java.net/~mr/jigsaw/spec/api/java.base-summary.html
[3] http://cr.openjdk.java.net/~mcimadamore/reflection-manifesto.html
[4] https://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/Module.html
[5] http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.4.1
More information about the jpms-spec-experts
mailing list