本文主要研究下java9 opens与exports的区别

open及exports

open

  • open module

主要用于解决deep reflection问题,open的作用是表示该模块下的所有的包在runtime都允许deep reflection( 包括public及private类型)
但是编译时期,仅仅允许该module中声明过exports的包可以访问,如果没有exports则该包的类在编译时期不可读

  • opens package

用于声明该模块的指定包在runtime允许使用反射访问

exports

表示允许在编译时和运行时访问指定包的public成员

open及exports对反射的影响

反射方法

  • 目标类
package com.packt.lib.sub1;
public class Sub1Service {public Sub1Service() {System.out.println("Sub1Service being instanced");}public void publicMethod() {System.out.println("public method called!");}protected void protectedMethod(){System.out.println("protected method called...");}private void privateMethod(){System.out.println("private method called...");}
}
  • 访问类名反射
        Sub1Service sub1Service = new Sub1Service();Method privateMethod = sub1Service.getClass().getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(sub1Service);
  • 通过包名反射
        Optional<Module> optional = ModuleLayer.boot().findModule("packt.lib");Class clz = Class.forName(optional.get(),"com.packt.lib.sub1.Sub1Service");Object sub1 = clz.newInstance();System.out.println(sub1.getClass().getMethods());Method publicMethod = sub1.getClass().getDeclaredMethod("publicMethod");publicMethod.invoke(sub1);Method protectedMethod = sub1.getClass().getDeclaredMethod("protectedMethod");protectedMethod.setAccessible(true);protectedMethod.invoke(sub1);Method privateMethod = sub1.getClass().getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(sub1);

没有exports,也没有opens

  • module-info.java
module packt.lib {exports com.packt.lib;
}

这里没有exports及opens com.packt.lib.sub1

  • 通过类名反射(编译报错)
Exception in thread "main" java.lang.IllegalAccessException: class com.packt.App (in module packt.main) cannot access class com.packt.lib.sub1.Sub1Service (in module packt.lib) because module packt.lib does not export com.packt.lib.sub1 to module packt.mainat java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)at java.base/jdk.internal.reflect.Reflection.ensureMemberAccess(Reflection.java:107)at java.base/java.lang.Class.newInstance(Class.java:553)at packt.main/com.packt.App.main(App.java:25)
  • 通过包名反射(newInstance运行时报错)
Exception in thread "main" java.lang.IllegalAccessException: class com.packt.App (in module packt.main) cannot access class com.packt.lib.sub1.Sub1Service (in module packt.lib) because module packt.lib does not export com.packt.lib.sub1 to module packt.mainat java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)at java.base/jdk.internal.reflect.Reflection.ensureMemberAccess(Reflection.java:107)at java.base/java.lang.Class.newInstance(Class.java:553)at packt.main/com.packt.App.main(App.java:26)

没有exports,有opens

  • module-info.java
module packt.lib {exports com.packt.lib;opens com.packt.lib.sub1;
}
  • 通过类名反射

由于没有exports,则编译不过

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.6.2:compile (default-compile) on project main: Compilation failure
[ERROR] /Users/demo/java9-multi-module-demo/main/src/main/java/com/packt/App.java:[30,41] 程序包 com.packt.lib.sub1 不可见
[ERROR] (程序包 com.packt.lib.sub1 已在模块 packt.lib 中声明, 但该模块未导出它)
  • 通过包名反射

像上面那种直接引用包名来反射的,不会报错,因为编译可以通过,运行正常

有exports,没有opens

module packt.lib {exports com.packt.lib;exports com.packt.lib.sub1;
}
  • 通过类名反射

可以编译通过,运行报错

Sub1Service being instanced
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make private void com.packt.lib.sub1.Sub1Service.privateMethod() accessible: module packt.lib does not "opens com.packt.lib.sub1" to module packt.mainat java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:198)at java.base/java.lang.reflect.Method.setAccessible(Method.java:192)at packt.main/com.packt.App.main(App.java:44)
[ERROR] Command execution failed.
  • 通过包名反射

可以编译通过,运行报错

Sub1Service being instanced
[Ljava.lang.reflect.Method;@4157f54e
public method called!
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make protected void com.packt.lib.sub1.Sub1Service.protectedMethod() accessible: module packt.lib does not "opens com.packt.lib.sub1" to module packt.mainat java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:198)at java.base/java.lang.reflect.Method.setAccessible(Method.java:192)at packt.main/com.packt.App.main(App.java:34)
[ERROR] Command execution failed.

直接open整个module,但是没有exports

  • module-info.java
open module packt.lib {exports com.packt.lib;
}
  • 直接访问类反射

这种情况,如果是直接访问该类来使用反射,由于没有exports该package,则直接编译报错

  • 通过包名反射

这种情况编译可以通过,运行正常

直接open整个module,也有exports

open module packt.lib {exports com.packt.lib;exports com.packt.lib.sub1;
}

两种访问方式的反射均正常编译及运行。

小结

  • open表示允许运行时通过反射使用

open的作用是表示该模块下的所有的包在runtime都允许deep reflection( 包括public及private类型);opens package的作用只是允许该包在runtime都允许deep reflection

open及opens都仅仅是开放runtime时期的可以通过反射访问(蕴含了运行时的exports)。

  • exports表示允许访问指定包的public成员(编译及运行时)

如果反射不直接通过类名调用,只是运行时通过包名使用,则只需open或opens即可
如果是通过类名来反射,由于用到了该类,需要通过exports指定可以访问,不指定则编译期立即报错
如果是通过类名来反射使用public方法或newInstance,如果没有exports,则运行时报错
如果有exports,但是没有open,因此编译通过运行时报错

  • illegal-access

--illegal-access默认是permit,表示允许unnamed modules反射(java.lang.reflect/java.lang.invoke)使用所有named modules中的类

doc

  • Java 9 揭秘(2. 模块化系统)

java9 opens与exports的区别 1相关推荐

  1. java9 opens与exports的区别

    为什么80%的码农都做不了架构师?>>>    序 本文主要研究下java9 opens与exports的区别 open及exports open open module 主要用于解 ...

  2. module是什么类型_nodejs中module.exports和exports的区别

    本文同步发表在我的个人博客中: 沧沧凉凉​www.cclliang.com 最近在学习nodejs,这篇文章就权当是一篇笔记,如果有什么地方有误,望指出. 先说说它们之间的区别: exports只能使 ...

  3. module.exports和exports得区别

    对module.exports和exports的一些理解 可能是有史以来最简单通俗易懂的有关Module.exports和exports区别的文章了. exports = module.exports ...

  4. Node.js: exports 和 module.exports 的区别

    我理解的exports 和 module.exports 的区别,欢迎大家吐槽~ 为了更好的理解 exports 和 module.exports 的关系,我们先来补点 js 基础.示例: app.j ...

  5. nodejs中module.exports和exports的区别

    最近在学习nodejs,这篇文章就权当是一篇笔记,如果有什么地方有误,望指出. 首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念. CommonJS模块规范 Com ...

  6. exports和module.exports的区别

    请牢记一条原则:无论使用 exports 暴露成员,或是 module.exports 暴露成员,最终暴露的结果,都是以 module.exports 所指向的对象为准. 1.module 对象 看一 ...

  7. module.export和exports两者区别及使用方法

    参考链接:简书博客.简书博客.CommonJS规范 功能介绍 module.exports Node应用由模块组成,采用CommonJS模块规范.根据这个规范,每个文件就是一个模块,有自己的作用域.在 ...

  8. 一句话说清楚NodeJS中module.exports和exports的区别

    关于这个问题NodeJS的官方文档中有一句很精辟的解释: What's the difference between module.exports and exports? The first exp ...

  9. node.js中exports与module.exports的区别分析

    前言 关于Node.js中的exports和module.exports,很多时候都比较容易让人混淆,弄不清楚两者间的区别.那么我们就从头开始理清这两者之间的关系. 来源 在开发Node.js应用的时 ...

最新文章

  1. Webhooks上的一个简单方法:恐吓现在停止
  2. 按一行一行的方法将一个文本文件复制到另一个文件中_大文件上的结构化数据计算示例...
  3. 解决修改“文件夹选项”后仍不能显示隐藏文件一例
  4. java 获取麦克_Java Sound API-捕获麦克风
  5. 100m和1000m网线的常见制作方法
  6. 电话光端机的电话接口类型有哪些?
  7. php class variable,解决关于PHP“Undefined variable”变量未定义
  8. Practice Lab 7:路由再分发
  9. 高倍数泡沫装置PHP_移动式高倍数泡沫灭火装置
  10. Java lambda list转换map时,把多个参数拼接作为key
  11. 教你用 FRP 自建 Teamview 连接避开商业检测
  12. 【Hive】日期函数
  13. BZOJ 3238 【AHOI2013】 差异
  14. SQLMAP安装及详解
  15. 递归与分治策略之利用中位数线性时间选择
  16. 西门子PLC S7-1200程序实例,版本博图V15及以上 西门子1200与安川机器人TCP/IP通讯,包含机器人GSD文件
  17. 数据分析师面试题目_数据分析师常见的10道面试题解答
  18. store buffer and invalidate queues
  19. 神经同步预测儿童学习新单词的能力
  20. transferTo和transferFrom

热门文章

  1. python读取idx_通过Python从.idx3-ubyte文件或GZIP中提取图像 - python
  2. 基于SEO的网站优化技术研究
  3. 百度网盘二维码显示失败
  4. TMS320F28374S之CMPSS
  5. @Override飘红
  6. 2020年鼠年二月初六 长发飘飘
  7. 数学分析_证明_第1章:可数个可数集之并为可数集
  8. 华为 mac地址防护
  9. C语言系列:2、数据类型、运算符和表达式
  10. Python推导式(列表推导式、元组推导式、字典推导式、集合推导式)