I try to create a demo to illustrate module encapsulation. I have 2 classes a.A and b.B in separate modules. module a requires b, and b is exported to a
package a;
import b.B;
class A{
public static void main(String[] args){
B b = new B();
}
}
package b;
public class B{
public B(){
System.out.println("B created");
}
}
module a {
requires b;
}
module b {
exports b to a;
}
├───class
├───jar
└───src
├───a
│ └───module-info.java
│ └───a
│ └───A.java
├───b
│ └───module-info.java
│ └───b
│ └───B.java
It works
>javac -d class --module-source-path src -m a
>jar -c -f jar/a.jar -e a.A -C class/a .
>jar -c -f jar/b.jar -C class/b .
>java -p jar -m a
B created
However, why I am able to access b.B from some other class in package default
import b.B;
class C{
public static void main(String[] a){
B b = new B();
}
}
>javac -cp ".;jar/b.jar" C.java
>java -cp ".;jar/b.jar" C
B created
openjdk version "17.0.1" 2021-10-19
Firstly, as far as I can see, you didn't explicitly put C
in a module. It is therefore in the "unnamed module". The unnamed module can read every observable module.
An unnamed module reads every observable module
It is designed this way so that old, non-modular code can still interact with new code.
Secondly, B
is also in the unnamed module when you run C
. This is because you put b.jar into the classpath, not the module path (--module-path
). In the modular world, you should use the module path to specify where the dependencies are, not the classpath.