Skip to content

包与模块

3.5 包

包是类的容器,提供了解决命名空间冲突的方案。
包在实际项目中对应了文件夹。对于一个项目,包的创建一般遵循倒域名的形式
例如:package io.localhost-8080.pojo

3.5.1 包的声明

  • 使用package关键字声明定义一个包。

  • 一个.java文件只允许存在一个package语句。

  • 包的声明必须放在.java文件的首行。

3.5.2 包的导入

  • 使用import关键字来导入别的包。

  • *为通配符,表示导入该包下所有类(不包括子包中的类)。

3.5.3 JDK 常用包

  • java.lang:核心包,在程序启动时自动加载到方法区,不需要手动导入

  • java.util:工具包,存放简化操作的工具类

  • java.io:数据传输

  • java.net:网络传输

  • java.math:数学运算

  • java.sql:数据库相关

  • java.awt:图形用户界面

  • java.security:数据安全

  • javax.xxx:扩展

  • org.xxx:第三方厂商、开源社区提供的包

注意

  • 包名不能以javajavax或者org开头。

  • 同包,或lang包下的类不使用import语句导入

3.6 模块Java 9.0+

Java 在 9.0 引入了平台模块系统(Java Platform Module System, JPMS)。模块是一个命名的、自我描述的代码与数据的集合。每个模块被组织成多个包、相关的资源文件和静态信息,每个包中又包含类与接口。
通过引入模块化系统,可以提供 JRE 定制化;避免类路径加载机制带来的依赖混乱;更强大的封装,声明哪些组件可以访问哪些不可以;它也配合 JVM 的优化提升了 Java 的性能。

语法:module 名称 {...}
同样使用倒域名形式来命名模块。

  • 依赖
    • 普通依赖
      在大括号中,如果有其他模块需要被依赖进来时使用关键词 requires 模块名
    • 可选依赖
      指定模块在编译时必要但运行时可选,用关键字 requires static 模块名 指明
    • 隐含可读依赖
      指定对另一个模块的依赖并确保访问当前模块的模块也会依赖该模块,用关键字 requires transitive 模块名 指明
  • 导出
    • 普通导出
      当需要指定模块中哪些包可以被其他模块使用时使用关键字 exports 包名. 被导出的包的公共类型是出于可见窗台的。当一个模块没有 exports 项时,它不向其他模块输出任何类型
    • 指向导出
      当需要明确模块中的某个包只向某些特定模块导出时,使用 exports 包名 to 模块名, 模块名, ... 指明。被指明的模块是多个时,其之间用逗号隔开。也称为合资格导出
  • 使用
    需配合 service 的概念使用。表示该模块使用了某 service.
    当一个包中包含了一些接口或者抽象类的具体实现时,这个实现的具体实例称为一个 service.
    uses 接口/抽象类
    这个命令表示当前模块是某些 service 的消费者。
  • 提供
    需配合 service 的概念使用。表示该模块提供了某些 service 的实现。
    provides 接口/抽象类 with 接口或抽象类的实现类名
    其中 provides 后面跟的接口或抽象类名就会是其他模块的使用命令中 uses 后面的内容。
    这个命令表示当前模块是某些 service 的生产者。
  • 开放
    为了强封装性,模块默认不可以通过反射来访问其他模块中的类型,除非它们是公有的
    • 仅运行时可访问某包
      当想要求一个模块当中的包只能在运行时被其他模块所访问时,使用命令 opens 包名
      该命令也符合反射
    • 仅某模块可运行时可访问某包
      当想指定模块中的某个包只能在运行时被指定的模块所访问时,使用命令 opens package to 包名, 包名, ...
      该命令也符合反射
    • 整个模块运行时可访问
      当整个模块里的包都可以在运行时被其他模块所访问时,使用命令:
      open module 模块名 {}

模块的声明源文件被保存为 module-info.java 存放在模块的根目录中。它会被编译成 module-info.class 而输出到输出目录。这样做的目的是使得模块声明有一个精确的定义和可扩展的格式。

java
// 简单声明
module com.foo.bar {}

// 依赖其他模块的模块
module com.foo.bar {
    requires io.localhost-8080;
}

// 指定可以被其他模块使用的类
module com.foo.bar {
    exports com.foo.bar.alpha;
    exports com.foo.bar.beta;
}

实际上,从 Java 9.0 开始整个 Java 源码也是以模块系统形式组织的。其中表示语言基础的模块被命名为 java.base,它是 Java 的核心包,其他每个模块都隐式依赖基础模块。