Day20:银河帝国

Java 9开始推出了模组(Module)系统,让Java的结构更为严谨,并且提升JVM载入类别的效率(就是我们常常import一大堆类别那边)。

什麽叫做更为严谨呢?原本我们要取用其他类别时,只要在要取用的类别中import进被取用的类别就好了,剩下就是看修饰子看不看得到而已;而在module中,还要定义类别可以给那些其他模组取用
packageVsModule
上图右侧,当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>;
}
  • requires
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用到
}
  • exports
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。
  • opens
    语法规则与exports一模一样,差别在於开放出来的package,里面的class将不受封装子的规定,只要被open出来,就算是private的class或variable,都可被所open的对象reflection到。
    还有加在module前面的open语法:
open module demos {}

这表示所有其他的module都将可以取用该module的package,这就相当於以往的package运作规则了。

  • uses & provides
    在谈uses与provides以前,要先谈谈ServiceLoader。主要分为Service和Provider两个角色,Service其实就是介面,而Provider就是实作介面的类别,以下就直接以Service与Provider当作module的名字(实际上取什麽都可以):

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

[Day11] Face Detection - 使用OpenCV & Dlib:Dlib HOG + Linear SVM

不要被标题一堆名词吓到;当你用过它後,你会惊讶它的易用以及,最重要的,无缝接轨辨识人脸关键点 本文...

Day15 - BST(Delete Case 1)

大家好,我是长风青云。今天是铁人赛第十五天。 今天心情有点糟,有点感慨。原谅我东西很少。详细内容我等...

Day14 - [丰收款] 使用Heroku Postgres资料库,存储订单交易资讯

昨天成功将Django网站布署到Heroku上,当然我们会需要撰写BackendURL页面来让API...

Button设计 自动跑码

今天推荐一个我觉得还蛮好用的辅助工具。 Android Button Maker 他是一个可以让你在...

简报版-第六章-谈谈手机APP下载安全吗?

其实原本最初规画想要做Index方式的纪录,然後多增加一些没写到的面向 不过,总是计画赶不上变化 ...