java9 jdk 文档_Java 9 揭秘(8. JDK 9重大改变下)

Tips

做一个终身学习的人。

340965388320

Java 9

六. 资源命名语法

资源使用由斜线分隔的字符串序列命名,例如com/jdojo/states.png,/com/jdojo/words.png和logo.png。 如果资源名称以斜线开头,则被视为绝对资源名称。

使用以下规则从资源名称中估算包(package)的名称:

如果资源名称以斜线开头,删除第一个斜线。 例如,对于资源名称/com/jdojo/words.png,此步骤将导致com/jdojo/words.png。

从最后一个斜线开始删除资源名称中的所有字符。 在这个例子中,com/jdojo/words.png导致com/jdojo。

用点号(.)替换名称中的每个剩余的斜线。 所以,com/jdojo被转换成com.jdojo。 生成的字符串是包名称。

有些情况下使用这些步骤会导致一个未命名的包或一个无效的包名称。 包名称(如果存在)必须由有效的Java标识符组成。 如果没有包名称,它被称为未命名的包。 例如,将META-INF/resource /logo.png视为资源名称。 应用上一组规则,其包名称将被计算为“META-INF.resources”,它不是有效的包名,但它是资源的有效路径。

七. 查找资源的规则

由于向后兼容性和对模块系统的强封装的承诺,JDK 9中查找资源的新规则是复杂的,基于以下几个因素:

包含资源的模块类型:命名的,开放的,未命名的或自动命名的模块;

正在访问资源的模块:它是同一个模块还是另一个模块?

正在被访问的资源的包名称:它是否是有效Java包? 这是一个未命名的包?

封装包含资源的包:将包含资源的包导出,打开或封装到访问资源的模块?

正在访问的资源的文件扩展名:资源是.class文件还是其他类型的文件?

正在使用哪种类的方法来访问资源:Class,ClassLoader或Module类?

以下规则适用于包含资源的命名模块:

如果资源名称以.class结尾,则可以通过任何模块中的代码访问资源。 也就是说,任何模块都可以访问任何命名模块中的类文件。

如果从资源名称计算的包名称不是有效的Java包名称,例如META-INF.resources,则可以通过任何模块中的代码访问该资源。

如果从资源名称计算的包名称是未命名的包,例如对于资源名称(如word.png),则可以通过任何模块中的代码访问该资源。

如果包含该资源的软件包对访问该资源的模块开放,则资源可以通过该模块中的代码访问。 一个包对模块开放,因为定义包的模块是一个开放的模块,或者模块打开所有其他模块的包,或者模块只使用一个限定的打开语句打开包。 如果没有以任何这些方式打开包,则该包中的资源不能被该模块外的代码访问。

这个规则是上一个规则的分支。 打开未命名,自动或开放模块中的每个包,因此所有其他模块中的代码都可以访问这些模块中的所有资源。

Tips

命名模块中的包必须打开,而不是导出,以访问其资源。 导出一个模块的包允许其他模块访问该包中的公共类型(而不是资源)。

在访问命名模块中的资源时,Module,Class和ClassLoader类中的各种资源查找方法的行为有所不同:

可以使用Module类的getResourceAsStream()方法来访问模块中的资源。 此方法是调用方敏感的。 如果调用者模块不同,则此方法将应用所有资源可访问性规则,如上所述。

在指定模块中定义的类的Class类中的getResource *()方法仅在该命名模块中定位资源。 也就是说,不能使用这些方法来定位定义调用这些方法的类的命名模块之外的类。

ClassLoader类中的getResource *()方法基于前面描述的规则列表来定位命名模块中的资源。 这些方法不是调用者敏感的。 在尝试查找资源本身之前,类加载器将资源搜索委托给其父类。 这些方法有两个例外:1)它们仅在无条件打开的包中定位资源。 如果使用限定的打开语句打开包,则这些方法将不会在这些包中找到资源。 2)它们搜索在类加载器中定义的模块。

Class对象将仅在它所属的模块中找到资源。 它还支持以斜线开头的绝对资源名称,以及不以斜线开头的相对资源名称。 以下是使用Class对象的几个示例:

// Will find the resource

URL url1 = Test.class.getResource("Test.class");

// Will not find the resource because the Test and Object classes are in different modules

URL url2 = Test.class.getResource("/java/lang/Object.class");

// Will find the resource because the Object and Class classes are in the same module, java.base

URL url3 = Object.class.getResource("/java/lang/Class.class");

// Will not find the resource because the Object class is in the java.base module whereas

// the Driver class is in the java.sql module

URL url4 = Object.class.getResource("/java/sql/Driver.class");

使用Module类定位资源需要具有该模块的引用。 如果可以访问该模块中的类,则在该Class对象上使用getModule()方法给出了模块引用。 这是获取模块引用的最简单方法。 有时候,你把模块名称作为字符串,而不是该模块中的类的引用。 可以从模块名称中找到模块引用。 模块被组织成由java.lang包中的ModuleLayer类的实例表示的层。 JVM至少包含一个boot 层。 boot层中的模块映射到内置的类加载器 —— 引导类加载器,平台类加载器和应用程序类加载器。 可以使用ModuleLayer类的boot()静态方法获取boot层的引用:

// Get the boot layer

ModuleLayer bootLayer = ModuleLayer.boot();

一旦获得boot层的引用,可以使用其findModule(String moduleName)方法获取模块的引用:

// Find the module named com.jdojo.resource in the boot layer

Optional m = bootLayer.findModule("com.jdojo.resource");

// If the module was found, find a resource in the module

if(m.isPresent()) {

Module testModule = m.get();

String resource = "com/jdojo/resource/opened/opened.properties";

InputStream input = module.getResourceAsStream(resource);

if (input != null) {

System.out.println(resource + " found.");

} else {

System.out.println(resource + " not found.”);

}

} else {

System.out.println("Module com.jdojo.resource does not exist");

}

八. 访问命名模块中的资源的示例

在本部分中,将看到资源查找规则的具体过程。 在com.jdojo.resource的模块中打包资源,其声明如下所示。

// module-info.java

module com.jdojo.resource {

exports com.jdojo.exported;

opens com.jdojo.opened;

}

该模块导出com.jdojo.exported包,并打开com.jdojo.opened包。

以下是com.jdojo.resource模块中所有文件的列表:

module-info.class

unnamed.properties

META-INF\invalid_pkg.properties

com\jdojo\encapsulated\encapsulated.properties

com\jdojo\encapsulated\EncapsulatedTest.class

com\jdojo\exported\AppResource.class

com\jdojo\exported\exported.properties

com\jdojo\opened\opened.properties

com\jdojo\opened\OpenedTest.class

有四个类文件。 在这个例子中,只有module-info.class文件很重要。 其他类文件定义一个没有任何细节的同名的类。 具有.properties扩展名的所有文件都是资源文件,其内容在此示例中不重要。 源代码包含Java9Revealed\com.jdojo.resource目录中这些文件的内容。

unnamed.properties文件在未命名的包中,因此可以通过任何其他模块中的代码来定位。 invalid_pkg.properties文件位于META-INF目录中,它不是有效的Java包名称,因此该文件也可以通过任何其他模块中的代码来定位。 com.jdojo.encapsulated包没有打开,所以encapsulated.properties文件不能通过其他模块中的代码来找到。 com.jdojo.exported包未打开,所以export.properties文件不能通过其他模块中的代码来找到。 com.jdojo.opened包是打开的,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值