由浅到深认识Java语言(51):JDK9新特性(模块化&REPL)

该文章Github地址:https://github.com/AntonyCheng/java-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】

在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】& CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

上一章:由浅到深认识Java语言(50):JDK8新特性

54.JDK9新特性

模块化

模块化的概念

Java 9 为了引入新的模块化的编程方式,特意增强和改进了一些功能,也添加了一些新的特性:

  1. Java程序编译运行过程中,引入了一个新的可选的阶段「链接时间」( linktime ),这个阶段介于编译时和运行时之间,在该阶段,可以组装和优化一组模块,可以使用 jLink 工具制作自定义运行时镜像 ( image );
  2. javac 、jlink 和 java 三个命令都添加了一些可选项用于指定模块路径,这些选项用于指定模块的定义位置;
  3. 增强 JAR 格式,更新 JAR 格式更新为模块化 JAR ,并且在 JAR 根目录下包含 module-info.class 文件;
  4. 引入了 JMOD 格式,这种一种类似于 JAR 的新的打包格式,这种格式中可以包含本地( native )代码和配置文件;
  5. 特意引入了 module 关键字,用于定义一个模块,不过这个关键字仅限于 module-info.java 中使用。

从 Java 9 为模块化的改变来看,Java 9 中的模块化其实就是一个 JAR 或 JMOD 格式的归档文件,该归档文件里包含了一些代码和数据还有一些配置文件,其中一定包含了一个名为 module-info.class 的文件,在该文件中定义了模块的一些信息。

创建一个 Java 9 模块

假设我们要定义一个 Java 9 模块,模块名为 top.sharehome.module.test ,工作目录为 D:\module\java ,项目名为 test-module

1、首先创建相关目录:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意,目录名和模块名要一致。

如果使用 tree . 命令,可以看到目录结构如下:

d:\module\java\test-module\src>tree .
卷 Data 的文件夹 PATH 列表
卷序列号为 0E27-4777
D:\MODULE\JAVA\TEST-MODULE\SRC
└─top.sharehome.module.test

d:\module\java\test-module\src>

2、在 \src\top.sharehome.module.test 目录下新建一个名为 module-info.java 文件,并输入以下内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3、添加源码包,假设测试代码都处于 top.module.test 包下,那么就要在 \src\top.sharehome.module.test 目录下再创建目录 top\module\test

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4、然后在这个称之为 top\module\test 的包下创建一个名为 ModuleTester.java 的文件,用于测试目的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是是方便起见,也是管理,所以将源代码及其包放在模块的目录下。

5、和 src 同级文件夹下创建一个文件夹 mods,然后再这个目录下创建一个和模块名相同的目录结构,如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6、接下来,跳转到 d:\module\java\test-module\ 目录,并使用下面的命令来编译模块;

D:\module\java\test-module>javac -d mods/top.sharehome.module.test src/top.sharehome.module.test/module-info.java src/top.sharehome.module.test/top/module/test/ModuleTester.java

上面的命令运行完之后,目录结构如下:

D:\module\java\test-module>tree /F
卷 Data 的文件夹 PATH 列表
卷序列号为 0E27-4777
D:.
├─mods
│  └─top.sharehome.module.test
│      │  module-info.class
│      │
│      └─top
│          └─module
│              └─test
│                      ModuleTester.class
│
└─src
    └─top.sharehome.module.test
        │  module-info.java
        │
        └─top
            └─module
                └─test
                        ModuleTester.java

7、还是在当前目录下就可以使用 java 命令来运行刚刚编译好的模块了:

D:\module\java\test-module>java --module-path mods -m top.sharehome.module.test/top.module.test.ModuleTester
Hello World!

REPL(JShell)

REPL ,全称 Read Eval Print Loop ,中文 「交互式解释器」,其实,就是一种代码所见即所得的即时编译器,Java 9 引入了 REPL ,并将其命令为 「 JShell 」 ,这真是我们 Java 开发的福音,以后演示代码的时候再也不用搬着一个 IDE 到处跑了,对于我们 Java 开发者来说,应该是 Java 9 带来的最大的个性吧。我们终于可以像 Python 、 Ruby 和 Node.js 那样在 Shell 可见即可得的运行一些范例代码,也就是说,使用 REPL,我们可以编写和测试基于 Java 的逻辑,无需使用 javac 进行编译,直接查看计算结果。

运行JShell

打开命令行终端,输入 jshell 进入 JShell,该启动过程有些缓慢:

D:\Dependence\Java11\bin>jshell.exe
|  欢迎使用 JShell -- 版本 11.0.14
|  要大致了解该版本, 请键入: /help intro

正如提示那样,我们可以输入 /help 来获得一些帮助:

jshell> /help
|  键入 Java 语言表达式, 语句或声明。
|  或者键入以下命令之一:
|  /list [<名称或 id>|-all|-start]
|       列出您键入的源
|  /edit <名称或 id>
|       编辑源条目
|  /drop <名称或 id>
|       删除源条目
|  /save [-all|-history|-start] <文件>
|       将片段源保存到文件
|  /open <file>
|       打开文件作为源输入
|  /vars [<名称或 id>|-all|-start]
|       列出已声明变量及其值
|  /methods [<名称或 id>|-all|-start]
|       列出已声明方法及其签名
|  /types [<名称或 id>|-all|-start]
|       列出类型声明
|  /imports
|       列出导入的项
|  /exit [<integer-expression-snippet>]
|       退出 jshell 工具
|  /env [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>] ...
|       查看或更改评估上下文
|  /reset [-class-path <路径>] [-module-path <路径>] [-add-modules <模块>]...
|       重置 jshell 工具
|  /reload [-restore] [-quiet] [-class-path <路径>] [-module-path <路径>]...
|       重置和重放相关历史记录 -- 当前历史记录或上一个历史记录 (-restore)
|  /history [-all]
|       您键入的内容的历史记录
|  /help [<command>|<subject>]
|       获取有关使用 jshell 工具的信息
|  /set editor|start|feedback|mode|prompt|truncation|format ...
|       设置配置信息
|  /? [<command>|<subject>]
|       获取有关使用 jshell 工具的信息
|  /!
|       重新运行上一个片段 -- 请参阅 /help rerun
|  /<id>
|       按 ID 或 ID 范围重新运行片段 -- 参见 /help rerun
|  /-<n>
|       重新运行以前的第 n 个片段 -- 请参阅 /help rerun
|
|  有关详细信息, 请键入 '/help', 后跟
|  命令或主题的名称。
|  例如 '/help /list''/help intro'。主题:
|
|  intro
|       jshell 工具的简介
|  keys
|       类似 readline 的输入编辑的说明
|  id
|       片段 ID 以及如何使用它们的说明
|  shortcuts
|       片段和命令输入提示, 信息访问以及
|       自动代码生成的按键说明
|  context
|       /env /reload 和 /reset 的评估上下文选项的说明
|  rerun
|       重新评估以前输入片段的方法的说明

如果要查看某个具体的命令的帮助信息,可以输入 /help [command] 来获得,比如 /help intro 获取工具简介:

jshell> /help intro
|
|                                   intro
|                                   =====
|
|  使用 jshell 工具可以执行 Java 代码,从而立即获取结果。
|  您可以输入 Java 定义(变量、方法、类等等),例如:int x = 8
|  或 Java 表达式,例如:x + x
|  或 Java 语句或导入。
|  这些小块的 Java 代码称为“片段”。
|
|  这些 jshell 工具命令还可以让您了解和
|  控制您正在执行的操作,例如:/list
|
|  有关命令的列表,请执行:/help

查看JShell默认导入哪些包

可以使用 /imports 命令查看 JShell 默认导入了哪些包:

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*

使用import命令导入某个包或文件

jshell> import java.lang.*

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
|    import java.lang.*

使用JShell进行一些简单的数学运算

jshell> 6*8
$2 ==> 48

jshell> 12/8
$3 ==> 1

jshell> $2 + $3
$4 ==> 49

JShell 会将每一此执行的结果保存到一个以 $ 开始的变量中,而后面,我们就可以对这些变量进行引用。

JShell中默认的上下文

可以在 JShell 中使用平时在 Java 中使用的类和方法来获取当前的运行上下文。

1、获取当前的执行线程:

jshell> Thread.currentThread()
$5 ==> Thread[main,5,main]

2、获取当前执行的方法名:

jshell> Thread.currentThread().getStackTrace()[2].getMethodName()
$6 ==> "invoke0"

3、获取当前执行的类名:

jshell> Thread.currentThread().getStackTrace()[2].getClassName()
$7 ==> "jdk.internal.reflect.NativeMethodAccessorImpl"

在JShell中定义一些方法

因为内部方法和内部类的关系,还可以在 JShell 中定义和使用方法:

1、在一行定义:

jshell> int doubled(int i){ return i*2;}
|  已创建 方法 doubled(int)

2、在多行定义:

jshell> int add(int i,int j){
   ...> return i+j;
   ...> }
|  已创建 方法 add(int,int)

多行定义方法要遵循一条准则,就是每个换行位置必须是大括号或者双目运算符等表达式的内部换行才可以。

3、重定义:

jshell> int doubled(int i){ return i*2;}
|  已修改 方法 doubled(int)

4、调用方法:

jshell> add(3,2)
$11 ==> 5

jshell> doubled(9)
$13 ==> 18

退出JShell

jshell> /exit
|  再见

下一章:由浅到深认识Java语言(51):JDK9新特性(改进JavaDocs&共存JAR)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值