再谈Java9模块化
在之前已经提到了作为java9最重要的特性就是模块化。有了模块化java9变得更轻量级。在编译运行的时候可以更一步的节省资源。上一篇文章中提到了java9模块化的一些keyword。介绍的不全面,下面来补充介绍一下模块化中的keyword
exports
exports PackageName [to ModuleName {, ModuleName}] ;
定义对外暴露的包名(允许外部模块在运行
或编译
期间访问该包下面的所有public
、protect
文件或变量方法,而且允许外部模块通过反射可以访问到该包下的public
、protect
文件或者变量方法)。还可以指定具体to
哪个模块。这样就可以缩小对外暴露范围。只有指定的模块才可以使用该包下面的文件。否则编译报错。这样就可以对底层的模块进行保护,避免上层调用。
opens
opens PackageName [to ModuleName {, ModuleName}] ;
定义对外打开的包名(允许外部模块在运行
期间访问该包下的所有public
、protect
文件或变量方法,且允许外部模块通过反射访问的该包下的所有类型的资源)。所以opens
比exports
开放的权限大,但是要通过反射去获取。同样也可以定义具体to
哪个模块,指定授权该模块可访问。否则运行报错。
uses
uses TypeName ;
定义消费的服务类型。可以是一个具体的类,也可以是一个借口,或者一个注解类(不能是枚举)。然后定义后通过 java.util.ServiceLoader#load(Class)
方法可以加载到该服务的具体实现类。然后循环迭代调用。
provides
provides TypeName with TypeName {, TypeName} ;
定义服务提供者。结合上面的uses
使用。eg:在a
模块中我定义了接口A
,且定义了A
的实现AImpl
,然后我在b
模块中requires a; use A;
这样我在b
模块中使用ServiceLoader
加载A.class的时候就可以获得AImpl
实体。也可以在b
模块中新增A
的实现BImpl
,然后在b
模块文件中定义provides A with BImpl
。这样ServiceLoader
就可以获取到两个不同的实现(可以根据实际需要自定义选取哪个实现)。uses
和provides
是模块化里面对接口的增强。
eg:
module A
public interface ITest {
void t();
}
public class ATestImpl implements ITest {
@Override
public void t() {
System.out.println("ATestImpl");
}
}
module A {
exports a to B;
provides a.ITest with a.ATestImpl;
}
module B
public class TestImpl implements ITest {
@Override
public void t() {
System.out.println("TestImpl");
}
}
public class BTestImpl implements ITest {
@Override
public void t() {
System.out.println("BTestImpl");
}
}
module B {
requires A;
provides a.ITest with b.TestImpl;
uses a.ITest;
}
public static void main(String[] args) {
ServiceLoader<ITest> load = ServiceLoader.load(ITest.class);
load.stream().forEach(t -> t.get().t());
}
我在两个模块中定义了三个实现。但是我只声明了两个provides
在module-info
中,最终执行结果为
ATestImpl
TestImpl
java9的一些小结
- 模块化。简化java运行依赖,解耦jar包的依赖,增强封装特性等。
- 允许在接口中定义并实现私有方法。可以提供给接口的默认方法使用(
default,static
),这样多个默认方法且实现代码有重复可以通过这种方式重构,使代码变得简洁。 - 更方便的集合构建方式。可以直接使用
List.of(1,2,3,4)
这种方式来生成集合。系统会根据默认值推断出集合的类型。生成的集合是java.util.ImmutableCollections
不可变的。 - Stream新增
takeWhile,dropWhile,ofNullable
等方法。使stream操作流更灵活。还支持Optional转Stream - java工具大杀器
JShell
,直接在jdk9的bin目录下执行.jshell
就可以进入JShell脚本工具里。直接运行java代码。可以抛开繁琐的包名类名main方法等。你甚至只需要执行一段可执行的代码即可,不需要写方法。 - 其它还有很多,比如货币的支持,新的httpclient,轻量级json处理,简化进程API等等。