Java - 模块系统

Java模块系统简介

你好,有抱负的Java程序员!今天,我们将开始一段激动人心的旅程,深入了解Java的模块系统。作为你友好的邻居计算机科学老师,我将一步一步地引导你了解这个迷人的话题。如果你是编程新手,请不要担心——我们将从基础开始,一起逐步学习!

Java - Module System

什么是模块?

让我们从一个简单的类比开始。想象一下你在建造一个乐高城堡。每一个乐高积木代表一段代码,而说明书告诉你如何将它们组合在一起。在Java中,一个模块就像是你城堡中预先构建的部分——它是一组相关代码的集合,共同执行特定的功能。

在技术术语中,Java中的一个模块是一个自包含的代码单元,包括:

  1. 类和接口
  2. 资源(如图片或配置文件)
  3. 明确定义了它需要从其他模块获取的内容
  4. 声明了它提供给其他模块的内容

将其视为一个组织良好的工具箱,里面的每一样东西都有其位置和用途。

Java模块系统的特性

Java模块系统,在Java 9中引入,带来了一些令人兴奋的特性。让我们一一探索它们:

1. 强封装

记得你小时候有一个秘密盒子来存放你的宝藏吗?模块的工作方式类似。它们允许你决定你的代码的哪些部分对他人可见,哪些部分是你的“秘密宝藏”。

module com.myapp.secretbox {
exports com.myapp.secretbox.api;
}

在这个例子中,只有com.myapp.secretbox.api包中的类对其他模块可见。其他所有内容都被隐藏了!

2. 可靠的配置

模块明确地声明了它们需要从其他模块获取的内容。这就像在去杂货店之前创建一个购物清单——你知道你确切需要什么,而且不会忘记任何东西!

module com.myapp.kitchen {
requires com.myapp.fridge;
requires com.myapp.stove;
}

在这里,我们的kitchen模块表示它需要fridgestove模块才能正常工作。

3. 改进的性能

有了模块,Java可以更智能地只加载它需要的代码。这就像只打包你实际上会穿的衣物去旅行,而不是你的整个衣橱!

声明一个模块

现在,让我们卷起袖子创建我们的第一个模块。我们首先在我们的源代码目录的根目录中创建一个名为module-info.java的文件。

module com.myapp.greetings {
exports com.myapp.greetings.api;
}

这个简单的声明创建了一个名为com.myapp.greetings的模块,并使com.myapp.greetings.api包对其他模块可用。

添加依赖模块

有时,我们的模块可能需要使用其他模块中的代码。我们可以使用requires关键字指定这些依赖。

module com.myapp.greetings {
requires com.myapp.translations;
exports com.myapp.greetings.api;
}

在这个例子中,我们的greetings模块需要translations模块才能正确工作。

添加可选模块

如果我们有一个模块是很好,但不是绝对必要的呢?这就是可选模块派上用场的地方!

module com.myapp.greetings {
requires com.myapp.translations;
requires static com.myapp.fancyfonts;
exports com.myapp.greetings.api;
}

static关键字告诉Java,fancyfonts模块是可选的。我们的greetings模块即使没有它也可以工作,但如果它可用,可以使用fancyfonts

添加传递模块

有时,我们希望将我们的依赖传递给依赖我们的模块。我们可以使用transitive关键字来实现这一点。

module com.myapp.greetings {
requires transitive com.myapp.translations;
exports com.myapp.greetings.api;
}

现在,任何需要com.myapp.greetings的模块都将自动获得对com.myapp.translations的访问权限。

导出公共类

当我们想要使某些包对其他模块可用时,我们使用exports关键字。

module com.myapp.greetings {
exports com.myapp.greetings.api;
exports com.myapp.greetings.utils to com.myapp.testing;
}

在这个例子中,我们将api包提供给所有模块,但utils包只对com.myapp.testing模块可用。

允许反射

有时,我们需要允许其他模块对我们的类使用反射。我们可以使用opens关键字来实现。

module com.myapp.greetings {
exports com.myapp.greetings.api;
opens com.myapp.greetings.internal to com.myapp.testing;
}

这允许com.myapp.testing模块对com.myapp.greetings.internal包中的类使用反射。

创建和使用Java模块

现在我们已经介绍了基础知识,让我们把它放在一起创建一个简单的模块化应用程序。我们将创建两个模块:com.myapp.greetingscom.myapp.main

首先,让我们创建com.myapp.greetings模块:

// module-info.java
module com.myapp.greetings {
exports com.myapp.greetings;
}

// com/myapp/greetings/Greeter.java
package com.myapp.greetings;

public class Greeter {
public static String greet(String name) {
return "Hello, " + name + "!";
}
}

现在,让我们创建一个使用我们的greetings模块的com.myapp.main模块:

// module-info.java
module com.myapp.main {
requires com.myapp.greetings;
}

// com/myapp/main/Main.java
package com.myapp.main;

import com.myapp.greetings.Greeter;

public class Main {
public static void main(String[] args) {
System.out.println(Greeter.greet("Java Modules"));
}
}

要编译和运行这个模块化应用程序,我们使用以下命令:

javac -d mods --module-source-path src $(find src -name "*.java")
java --module-path mods -m com.myapp.main/com.myapp.main.Main

瞧!你刚刚创建并运行了你的第一个模块化Java应用程序。

结论

恭喜你完成了对Java模块系统的介绍!我们已经介绍了很多内容,从理解模块是什么到在真实应用程序中创建和使用它们。请记住,就像学习骑自行车一样,掌握模块需要练习。不要害怕实验和犯错误——这是我们学习的最佳方式!

在你继续Java之旅时,你会发现模块帮助你创建更组织化、更安全、更高效的应用程序。它们就像是将你的编程技能从好提升到优秀的秘密成分。

继续编码,继续学习,最重要的是,玩得开心!下次见,愉快的模块化!

Credits: Image by storyset