24段魔尺拼图指南_拼图项目动手指南

24段魔尺拼图指南

Jigsaw项目将把模块化引入Java平台,根据原始计划,它将在12月10日完成功能。 所以我们在这里,但拼图在哪里?

在过去的六个月中肯定发生了很多事情: 原型问世 ,内部API的迫在眉睫的删除引起了很大的骚动 , 邮件列表中充斥着有关项目设计决策的重要讨论 ,而JavaOne看到了一系列很棒的介绍性演讲 。拼图团队。 然后Java 9因拼图而延迟了半年 。

但是,让我们暂时忽略所有这些,仅关注代码。 在本文中,我们将使用一个现有的演示应用程序并将其与Java 9进行模块化。如果要继续学习,请转到GitHub ,在该处可以找到所有代码。 设置说明对于使脚本在Java 9中运行非常重要。为简便起见,我从本文的所有程序包,模块和文件夹名称中删除了前缀org.codefx.demo

拼图之前的应用

即使我竭尽全力不理会整个圣诞节,但让演示程序保持本季精神似乎是审慎的做法。 因此,它为出现日历建模:

  • 有一个日历,其中包含24个日历表。
  • 每张纸都知道它的月份,并包含一个惊喜。
  • 即将到圣诞节的死亡游行象征着将床单(以及惊喜)印刷到控制台上。

当然,需要首先创建日历。 它可以自己做到这一点,但它需要一种创造惊喜的方法。 为此,它得到了一个惊喜工厂清单。 main方法如下所示:

public static void main(String[] args) {List<SurpriseFactory> surpriseFactories = Arrays.asList(new ChocolateFactory(),new QuoteFactory());Calendar calendar =Calendar.createWithSurprises(surpriseFactories);System.out.println(calendar.asText());
}

该项目的初始状态绝不是拼图之前最好的。 相反,这是一个简单的起点。 它由一个包含所有必需类型的模块(从抽象的意义上讲,不是Jigsaw解释)组成:

  • “惊喜API” – SurpriseSurpriseFactory (均为接口)
  • “日历API” – CalendarCalendarSheet用于创建日历
  • 惊喜–几个SurpriseSurpriseFactory实现
  • Main –连接并运行整个过程。

编译和运行很简单(Java 8的命令):

# compile
javac -d classes/advent ${source files}
# package
jar -cfm jars/advent.jar ${manifest and compiled class files}
# run
java -jar jars/advent.jar

进入拼图土地

下一步虽小,但很重要。 它不会更改代码或其组织,只会将其移至Jigsaw模块中。

模组

那么什么是模块? 引用强烈推荐的模块系统状态 :

模块是命名的,自描述的代码和数据集合。 它的代码被组织为一组包含类型(即Java类和接口)的软件包。 其数据包括资源和其他种类的静态信息。

为了控制其代码如何引用其他模块中的类型,模块声明其需要哪些其他模块才能进行编译和运行。 为了控制其他模块中的代码如何引用其包中的类型,模块声明要导出的包中的哪个。

因此,与JAR相比,模块具有JVM可以识别的名称,声明其依赖于其他模块,并定义哪些包是其公共API的一部分。

名称

模块的名称可以是任意的。 但是为了确保唯一性,建议坚持使用包的反向URL命名模式。 因此,虽然这不是必需的,但通常意味着模块名称是它包含的软件包的前缀。

依存关系

一个模块列出了要编译和运行的其他模块。 对于应用程序和库模块而言,这都是正确的,但对于JDK本身中的模块而言,也是如此,该模块被分成了约80个(请使用java -listmods )。

再次从设计概述中:

当一个模块直接依赖于模块图中的另一个模块时,第一个模块中的代码将能够引用第二个模块中的类型。 因此,我们说第一模块读取第二模块,或者等效地,第二模块被第一模块读取

[…]

模块系统确保每个依赖关系都由另一个模块精确地满足,没有两个模块互相读取,每个模块最多读取一个定义给定程序包的模块,并且定义同名程序包的模块不会互相干扰。

当违反任何属性时,模块系统将拒绝编译或启动代码。 这是对脆弱类路径的巨大改进,在脆弱类路径中,例如丢失的JAR仅在运行时才发现,从而使应用程序崩溃。

还值得指出的是,只有模块直接依赖于另一个模块,才能访问另一个模块的类型。 因此,如果A依赖于B ,而B依赖于C ,则除非明确要求A ,否则A无法访问C。

出口产品

一个模块列出了它导出的软件包。 这些包中的公共类型只能从模块外部访问。

这意味着public不再是真正的公众。 非导出包中的公共类型与导出包中的非公共类型一样,对外界隐藏。 这比当今的私有包类型更加隐蔽,因为模块系统甚至不允许反射访问它们。 由于拼图是当前实现的,命令行标志是解决此问题的唯一方法。

实作

为了能够创建模块,项目在其根源目录中需要一个module-info.java

module advent {// no imports or exports
}

等等,我不是说我们也必须声明对JDK模块的依赖吗? 那么,为什么我们在这里没有提到什么呢? 所有Java代码都需要Object ,并且该类以及演示使用的其他少数几个类也是模块java.base一部分。 因此,实际上每个 Java模块都依赖于java.base ,这导致Jigsaw团队决定自动要求它。 因此,我们不必明确提及它。

最大的变化是要编译和运行的脚本(Java 9的命令):

# compile (include module-info.java)
javac -d classes/advent ${source files}
# package (add module-info.class and specify main class)
jar -c \--file=mods/advent.jar \--main-class=advent.Main \${compiled class files}
# run (specify a module path and simply name to module to run)
java -mp mods -m advent

我们可以看到编译几乎相同–我们只需要在类列表中包括新的module-info.java

jar命令将创建所谓的模块化JAR,即包含模块的JAR。 与之前不同,我们不再需要任何清单,而是可以直接指定主类。 注意如何在目录mods创建JAR。

完全不同的是启动应用程序的方式。 这个想法是要告诉Java在哪里可以找到应用程序模块(使用-mp mods ,这称为模块路径 ),以及我们想启动哪个模块(使用-m advent )。

分成模块

现在是时候真正地了解Jigsaw并将其拆分为单独的模块了。

虚构理由

“惊喜API”(即SurpriseSurpriseFactory取得了巨大的成功,我们希望将其与整体分离。

创造惊喜的工厂非常活跃。 这里要做很多工作,它们经常更改,并且使用的工厂因版本而异。 因此,我们想隔离它们。

同时,我们计划创建一个大型的圣诞节应用程序,日历仅是其中的一部分。 因此,我们也希望为此提供一个单独的模块。

我们最终得到以下模块:

  • 惊喜Surprise and SurpriseFactory
  • 日历 –日历,使用Surprise API
  • 工厂SurpriseFactory实现
  • main –原来的应用程序,现在已经镂空到Main

通过查看它们之间的依赖关系,我们可以发现惊喜并不取决于其他模块。 日历工厂都使用它的类型,因此必须依赖它。 最后, main使用工厂来创建日历,因此它依赖于两者。

图1_50066

实作

第一步是重新组织源代码。 我们将遵循官方快速入门指南建议的目录结构,并将所有模块放在src的自己的文件夹中:

src- advent.calendar: the "calendar" module- org ...module-info.java- advent.factories: the "factories" module- org ...module-info.java- advent.surprise: the "surprise" module- org ...module-info.java- advent: the "main" module- org ...module-info.java
.gitignore
compileAndRun.sh
LICENSE
README

为了保持可读性,我删节了org下面的文件夹。 缺少的是软件包以及每个模块的最终源文件。 完整地在GitHub上查看它。

现在,让我们看看这些模块信息必须包含什么以及如何编译和运行应用程序。

没有必要的条款,因为Surprise没有依赖性。 (除了java.base ,它始终是隐式必需的。)它导出包advent.surprise因为它包含两个类SurpriseSurpriseFactory

因此, module-info.java如下所示:

module advent.surprise {// requires no other modules// publicly accessible packagesexports advent.surprise;
}

编译和打包与上一节非常相似。 实际上,这甚至更容易,因为意外事件不包含任何主要类别:

# compile
javac -d classes/advent.surprise ${source files}
# package
jar -c --file=mods/advent.surprise.jar ${compiled class files}

日历使用来自Surprise API的类型,因此模块必须依赖Surprise 。 向模块添加requires advent.surprise即可实现。

该模块的API由Calendar类组成。 为了使其可公开访问,必须导出包含软件包advent.calendar 。 请注意,同一包专用的CalendarSheet在模块外部将不可见。

但有一个附加的扭曲:我们刚刚作出Calendar.createWithSurprises( List<SurpriseFactory> )公布,从惊喜模块暴露类型。 因此,除非读取日历的模块也需要惊讶 ,否则Jigsaw将阻止它们访问这些类型,这将导致编译和运行时错误。

将require子句标记为public可解决此问题。 有了它,任何依赖日历的模块也会让人吃惊 。 这称为隐式可读性

最终的模块信息如下所示:

module advent.calendar {// required modulesrequires public advent.surprise;// publicly accessible packagesexports advent.calendar;
}

编译几乎像以前一样,但是当然必须在此反映对惊奇的依赖。 为此,将编译器指向目录mods就足够了,因为它包含所需的模块:

# compile (point to folder with required modules)
javac -mp mods \-d classes/advent.calendar \${source files}
# package
jar -c \--file=mods/advent.calendar.jar \${compiled class files}

该工厂实现SurpriseFactory所以这个模块必须依靠惊喜 。 并且由于它们从已发布的方法返回Surprise实例,因此与上述相同的思路导致了requires public子句的出现。

可以在包advent.factories找到工厂,因此必须将其导出。 请注意,在另一个模块中找到的公共类AbstractSurpriseFactory在此模块外部无法访问。

这样我们得到:

module advent.factories {// required modulesrequires public advent.surprise;// publicly accessible packagesexports advent.factories;
}

编译和打包类似于日历

我们的应用程序需要日历工厂这两个模块进行编译和运行。 它没有要导出的API。

module advent {// required modulesrequires advent.calendar;requires advent.factories;// no exports
}

编译和打包与上一节的单个模块相似,不同之处在于编译器需要知道在哪里寻找所需的模块:

#compile
javac -mp mods \-d classes/advent \${source files}
# package
jar -c \--file=mods/advent.jar \--main-class=advent.Main \${compiled class files}
# run
java -mp mods -m advent

服务

拼图通过实现服务定位器模式实现松散耦合,其中模块系统本身充当定位器。 让我们看看情况如何 。

虚构理由

最近有人读了一篇有关冷松耦合的博客文章。 然后她从上面看我们的代码,抱怨主机工厂之间的紧密关系。 为什么还要知道工厂

因为…

public static void main(String[] args) {List<SurpriseFactory> surpriseFactories = Arrays.asList(new ChocolateFactory(),new QuoteFactory());Calendar calendar =Calendar.createWithSurprises(surpriseFactories);System.out.println(calendar.asText());
}

真? 只是为了实例化完美抽象的某些实现( SurpriseFactory )?

而且我们知道她是对的。 让其他人为我们提供实现将消除直接依赖。 更好的是,如果说中间人能够在模块路径上找到所有实现,则可以通过在启动之前添加或删除模块来轻松配置日历的惊喜。

拼图确实可以做到这一点。 我们可以有一个模块来指定它提供接口的实现。 另一个模块可以表示它使用所述接口,并使用ServiceLocator查找所有实现。

我们利用这个机会将工厂分割成巧克力,然后报价并最终得到以下模块和依赖项:

  • 惊喜Surprise and SurpriseFactory
  • 日历 –日历,使用Surprise API
  • 巧克力ChocolateFactory即服务
  • quoteQuoteFactory即服务
  • 主要 –应用程序; 不再需要单个工厂

图2_50066

实作

第一步是重新组织源代码。 与以前相比,唯一的变化是src/advent.factoriessrc/advent.factory.chocolatesrc/advent.factory.quote

让我们看一下各个模块。

两者都没有改变。

除某些名称外,两个模块都是相同的。 让我们看一下巧克力,因为它更美味。

工厂以前一样,该模块requires public 惊喜模块。

更有趣的是其出口。 它提供了SurpriseFactory的实现,即ChocolateFactory ,其实现如下指定:

provides advent.surprise.SurpriseFactorywith advent.factory.chocolate.ChocolateFactory;

由于此类是其公共API的全部,因此不需要导出其他任何内容。 因此,没有其他出口条款是必要的。

我们最终得到:

module advent.factory.chocolate {// list the required modulesrequires public advent.surprise;// specify which class provides which serviceprovides advent.surprise.SurpriseFactorywith advent.factory.chocolate.ChocolateFactory;
}

编译和打包很简单:

javac -mp mods \-d classes/advent.factory.chocolate \${source files}
jar -c \--file mods/advent.factory.chocolate.jar \${compiled class files}

关于main的最有趣的部分是它如何使用ServiceLocator查找SurpriseFactory的实现。 从其主要方法 :

List surpriseFactories = new ArrayList<>();
ServiceLoader.load(SurpriseFactory.class).forEach(surpriseFactories::add);

我们的应用程序现在仅需要日历,但必须指定它使用SurpriseFactory 。 它没有要导出的API。

module advent {// list the required modulesrequires advent.calendar;// list the used servicesuses advent.surprise.SurpriseFactory;// exports no functionality
}

编译和执行与以前一样。

我们确实可以通过简单地从模块路径中删除工厂模块之一来更改日历最终将包含的惊喜。 整齐!

摘要

就是这样了。 我们已经看到了如何将单片应用程序移动到单个模块中,以及如何将其拆分为多个模块。 我们甚至使用服务定位器将我们的应用程序与服务的具体实现分离开来。 所有这些都在GitHub上,因此请查看更多代码!

但是还有更多要讨论的! 拼图带来了一些不兼容问题,但也解决了许多不兼容问题。 而且我们还没有讨论反射如何与模块系统交互以及如何迁移外部依赖项。

如果您对这些主题感兴趣,请在我的博客上观看Jigsaw标签 ,因为在接下来的几个月中我一定会写关于它们的。

翻译自: https://www.javacodegeeks.com/2015/12/project-jigsaw-hands-guide.html

24段魔尺拼图指南

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql 解析 java_将Java 8流解析为SQL

sql 解析 java当Java 8发行并且人们开始流式处理各种东西时&#xff0c;不久之后他们就开始想象如果可以以相同的方式使用数据库将有多大的潜力。 本质上&#xff0c;关系数据库由以表状结构组织的巨大数据块组成。 这些结构非常适合进行过滤和映射操作&#xff0c;如SQL语言的…

杭州电子科技大学保研计算机,杭州电子科技大学计算机学院计算机科学与技术(一级学科)保研细则...

杭州电子科技大学计算机学院计算机科学与技术(一级学科)保研细则信息&#xff0c;是考研之前需要获取相应的考研信息&#xff0c;比如考试大纲、招考专业、招考目录等等基本信息&#xff0c;这些内容是进行考研前期工作的必要准备。考生可以从各院校的研招网进行查询&#xff0…

返回路径平面上的间隙_裁切机的上刀下刀如何调整?

每天都在使用裁切机时&#xff0c;由于各种因素往往会出现上刀、下刀现象(也称凸刀、凹刀现象)&#xff0c;给后面的套准带来困难。在此小编对上刀、下刀现象的产生原因做一分析与总结。01千斤压力不够(1)机械压力弹簧弹力不够。此时必须增大压力&#xff0c;如果增大到最大位置…

pcb板材的tg是什么_做到这6点,PCB过回焊炉不会出现板弯及板翘!

【维文信PCBworld】在PCB板子过回焊炉容易发生板弯及板翘&#xff0c;大家都知道&#xff0c;那么如何防止PCB板子过回焊炉发生板弯及板翘&#xff0c;下面就为大家阐述下&#xff1a;1.降低温度对PCB板子应力的影响既然「温度」是板子应力的主要来源&#xff0c;所以只要降低回…

java-ee-api_刷新器-Java EE 7概览

java-ee-api随着红帽JBoss企业应用平台7&#xff08;EAP 7&#xff09;的迫在眉睫&#xff0c;甚至WebLogic Server刚刚获得Java EE 7认证&#xff0c;我认为现在应该是时候对Java Enterprise Edition 7进行一些更新了。功能&#xff0c;并指向更多资源。 Java EE 7 –开发人员…

层 数据仓库_小尝试:基于指标体系的数据仓库搭建和数据可视化

关于作者&#xff1a;小姬&#xff0c;某知名互联网公司产品专家&#xff0c;对数据采集、生产、加工有所了解&#xff0c;期望多和大家交流数据知识&#xff0c;以数据作为提出好问题的基础&#xff0c;挖掘商业价值。0x00 前言我将整理文章分享数据工作中的经验&#xff0c;因…

计算机中级职称报考入口,2020年9月计算机职称考试报名流程(附入口)

2020年9月计算机等级报名公告正在陆续公布&#xff0c;计算机等级考试网上怎么报名&#xff1f;小编为大家整理计算机等级报名流程如下&#xff1a;2020年9月计算机等级报名流程一、注册通行证考生登入报名网页后&#xff0c;点击“用户注册”按钮&#xff0c;根据网页提示&…

简单工厂抽象工厂工厂方法_让工厂美丽

简单工厂抽象工厂工厂方法每个名副其实的Java程序员都知道Factory Pattern 。 这是一种便捷&#xff0c;标准化的方法&#xff0c;它通过教一个组件如何捕鱼而不是将它们交给它们来减少耦合。 但是&#xff0c;在使用大型系统时&#xff0c;该模式确实会向系统添加很多样板代码…

内蒙古大学计算机组成原理实验,内蒙古大学计算机组成原理期末练习0

内蒙古大学计算机组成原理期末练习0 (4页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;9.9 积分第 1 页 共 4 页 《《计算机组成原理计算机组成原理》》期末练习期末练习 班级 专业 姓名 学号 编号 …

dev的编辑器不支持getchar吗_“两头婚兴起”:你支持不娶不嫁,孩子随父姓也随母姓吗?...

何为两头婚&#xff1f;简单来说就是男不娶&#xff0c;女不嫁&#xff0c;没有彩礼也没有嫁妆的说法。男女俩人结婚之后没有谁到谁家里之说&#xff0c;两夫妻过自己的小日子&#xff0c;与各自的原生家庭保持一定的联系。婚后生育两个孩子&#xff0c;一个随父姓&#xff0c;…

全国计算机证件照要露耳朵吗,结婚证照片要露耳朵么 结婚登记照露一只耳朵行吗...

结婚证件照&#xff0c;这是可以在在民政局里面照的&#xff0c;也是可以在外面的影楼照的&#xff0c;在外面影楼照的话&#xff0c;照出来会比较好看&#xff0c;就是价格有点贵。结婚证上面的照片是证件照&#xff0c;所以是有一定的要求的。露一只耳朵行不行呢&#xff1f;…

findfirst_当心findFirst()和findAny()

findfirst过滤Java 8 Stream &#xff0c;通常使用findFirst()或findAny()来获取在过滤器中幸存的元素。 但这可能并不能真正实现您的意思&#xff0c;并且可能会出现一些细微的错误。 那么 从我们的Javadoc&#xff08; 此处和此处 &#xff09;可以看出&#xff0c;这两种方…

java流式传输对象_使用Java 8在地图上流式传输

java流式传输对象在本文中&#xff0c;我将向您展示如何在标准Java映射上有效地实现Speedment Open Source流&#xff0c;并将Stream接口扩展为MapStream&#xff01; 即使在复杂的情况下&#xff0c;此添加将使保持流的具体性和可读性变得更加容易。 希望这将允许您继续流式传…

oracle11g支持xp吗_拔掉U盘前一定需要安全弹出吗?

相信每一个使用过U盘的人&#xff0c;都经历过不安全弹出USB设备就直接拔掉&#xff0c;然后被电脑无情提示没有正确弹出USB设备的状况。拔掉U盘前点击安全弹出&#xff0c;已经成了一种默认的操作。那么&#xff0c;问题来了&#xff0c;拔掉U盘前真的需要安全弹出吗&#xff…

java中使用kotlin_在Kotlin中使用libGDX

java中使用kotlin最近&#xff0c;我一直在阅读有关不同语言的信息&#xff0c;以及它们可以为已经拥挤的软件开发人员带来什么&#xff0c;并且一种语言对我来说很突出&#xff1a;Kotlin。 &#xff08; https://kotlinlang.org/ &#xff09; 这是一种相对较新的语言&#…

同时防服务器维修,加强服务器日常运维,避免宕机灾难发生

原标题&#xff1a;加强服务器日常运维&#xff0c;避免宕机灾难发生服务器作为我们日常网络的支撑&#xff0c;可以说是24小时的全天候运转。在这种无休止的“加班”的状态下&#xff0c;服务器必然容易出问题&#xff0c;一旦发生服务器宕机就会造成整个网络的瘫痪&#xff0…

basemap安装_【我是解决安装问题系列_1】Mac python basemap安装

「2020/3/21更新」 附basemap网盘下载地址⏬Python需要跳过的安装的坑太太太太多了!!!!!最近看《利用python进行数据分析》这本书&#xff0c;到可视化的部分&#xff0c;看着最后的例子地图挺酷炫的&#xff0c;跟着敲代码的过程中&#xff0c;发现有时候不是你不会写&#xf…

nfs服务器远程访问,NFS远程共享存储

原标题&#xff1a;NFS远程共享存储构建储NFS远程共享存因为NFS有很多功能&#xff0c;不同的功能需要使用不同的端口。因此NFS无法固定端口。而RPC会记录NFS端口的信息&#xff0c;这样就能够通过RPC实现服务端和客户端的RPC来沟通端口信息。那RPC和NFS之间又是如何之间相互通…

ntp服务器查看终端,使用命令行界面使用NTP服务器在Windows中同步时间 | MOS86

即使使用简单的3V锂电池(CR2032)关闭电脑&#xff0c;每台台式电脑也能保持正确的时间。但这不是一个可充电电池&#xff0c;所以一年左右就停止工作了。您可以轻松地替换此单元格&#xff0c;但更换单元后&#xff0c;必须使用NTP服务器更新时间&#xff0c;以便Windows PC保持…

concat合并的数组会有顺序么_JS 数组操作 记录 笔记

Array数组的方法Mutator方法————"突变方法"会改变数组自身的值&#xff1b;Accessor方法————"访问方法"不会改变数组自身的值&#xff1b;Iteration方法————"遍历的方法" Establish方法————"创建新方法"Mutator方法(会…