Java中的模块是用来组织代码的,既然是组织功能,就必然涉及到访问控制。这里大致介绍一下模块中的高级访问控制。
假设有三个模块,分别叫firstModule、secondModule、thirdModule。第一个模块的描述符是这样的:
module firstModule {exports com.j11.first;}
后面两个模块都依赖了这个模块,并且都有自己的main方法,可以直接运行。
如果将导出语句修改为module firstModule {exports com.j11.first to secondModule;}
注意加粗的地方,使用了to关键字,标明第一个模块只能给第二个模块使用。这时候可以发现第二个模块可以正常引用第一个模块,但是第三个模块访问不了第一个模块了。
to关键字后面可以跟多个目标模块:
module firstModule {exports com.j11.first to secondModule, thirdModule;}
这样的话,可以看到所有模块都可以正常编译运行了。
有时候编译期并不需要依赖某个模块,只有运行期才用得上(比如反射)。比如我们有一个模块,里面有两个包,里面分别有一个类:
package com.j11.exportspublic class Exports {public void export() {System.out.println("export");Open open = new Open();System.out.println(open);}}package com.j11.open;public class Open {@Overridepublic String toString() {return "hi there";}}
当描述符如下时:
module openModule {exports com.j11.exports;}
很明显只有com.j11.exports.Exports 可以被requires到。但是如果在运行期访问不到是不行的,比如上面看到 Exports 引用了 Open 类,如果调用其export()方法就会报错:
java.lang.IllegalAccessException: Main (in module mainModule) cannot access class .Open (in module openModule) because module openModule does not export to module mainModule
为了克服这种意外,可以在描述符中使用 open 关键字:
open module openModule {exports com.j11.exports;}
使用open的意思是,模块内所有的public类型都可以在运行时访问,但只有明确exports的包才能在编译器访问。
除了使用open module,还有一种更加精细的运行时访问控制,就是使用opens关键字:
module openModule {exports com.j11.exports;opens com.j11.open;}
这样com.j11.exports包可以在编译器访问,com.j11.open可以在运行期访问;如果有其他包则任何时候无法访问。opens 语句中,也可以在包名后面使用to来指定只有哪个模块可以在运行时访问该包。
希望大家能掌握今天的内容!