Java 9开始推出了模组(Module)系统,让Java的结构更为严谨,并且提升JVM载入类别的效率(就是我们常常import一大堆类别那边)。
什麽叫做更为严谨呢?原本我们要取用其他类别时,只要在要取用的类别中import进被取用的类别就好了,剩下就是看修饰子看不看得到而已;而在module中,还要定义类别可以给那些其他模组取用:
上图右侧,当Square类别要import右边的圈圈时就会失败,因为右边圈圈所属的module没有声明要exports给Square所属module,就会import不到。
除了要多定义要给谁用外,映射的机制也需要额外定义能被取用的范围,原本映射的机制是可以无视封装修饰子的:
package flour;
public class Wheat{}
package flour;
class Manufacturer{
public String name;
public Integer est;
}
package bread;
import flour.Wheat;
import flour.Manufacturer; // 这边会报错,因为修饰子的关系,bread看不到flour中的Manufacturer类别
public class Baguette{
Class class = Class.forName("flour.Manufacturer");
Field[] fields = class.getFields(); // 透过映射就可以拿到不该看到的Manufacturer类别的属性
}
我们来看看module的语法:
module <this module name> {
requires <other module names>;
exports <packages of this module to other modules that require them>;
opens <packages of this module to other modules via reflection>;
uses <services provided by other modules>;
provides <services to other modules> with <service implementations>;
version <value>;
}
module com.some {
// requires java.base -> 这行会隐藏在所有的module中,代表引入Java SE的基础classes。
requires java.logging;
requires transitive org.acme; // 任何引用com.some的module也会需要org.acme,所以宣告transitive时,引用com.some的module不用额外再引用org.acme。
requires static com.foo; // 宣告static代表这个module只会在compile time用到
}
package demos.a;
public class L {}
package demos.a;
class M {}
package demos.b;
public class N {}
package demos.c;
public class O {}
module demos{
exports demos.a;
exports demos.b to other;
}
module other{
requires demos;
}
// module other可以引用到class L, class N;class M为default所以只能在demos.a这个package中被看见,class O所在的package demos.c没有被module exports,所以也没办法被其他module看见。
module foo{
requires demos;
}
// module foo可以引用到class L;class N只被exports给module other,所以这边看不见class N。
open module demos {}
这表示所有其他的module都将可以取用该module的package,这就相当於以往的package运作规则了。
Service:
module service{
exports service.a;
}
package service.a;
public interface L{}
Provider:
module provider{
requires service;
provides service.a.L with provider.b.M;
}
package provider.b;
public class M implements service.a.L{}
有了以上定义後,当有类别要使用这个Service时,在module中声明要取用哪个Service,并在程序码中透过ServiceLoader.load(Service类别),并呼叫.findFirst()找到第一个有提供该Service的Provider实作,或透过.iterator()找到需要的Provider:
module application{
requires service;
uses service.a.L;
}
public class Main{
public static void main(String[] args){
ServiceLoader<L> s1 = ServiceLoader.load(L.class);
L l = s1.findFirst().get();
}
}
<<: 30天打造品牌特色电商网站 Day.18 文字的样子
>>: Day 21. 条件渲染 – v-if、v-show
不要被标题一堆名词吓到;当你用过它後,你会惊讶它的易用以及,最重要的,无缝接轨辨识人脸关键点 本文...
大家好,我是长风青云。今天是铁人赛第十五天。 今天心情有点糟,有点感慨。原谅我东西很少。详细内容我等...
昨天成功将Django网站布署到Heroku上,当然我们会需要撰写BackendURL页面来让API...
今天推荐一个我觉得还蛮好用的辅助工具。 Android Button Maker 他是一个可以让你在...
其实原本最初规画想要做Index方式的纪录,然後多增加一些没写到的面向 不过,总是计画赶不上变化 ...