Intellij-IDEA-入门手册-全-
Intellij IDEA 入门手册(全)
一、入门指南
在本章中,我们将介绍以下内容:
-
要使用哪个版本
-
[计] 下载
-
安装和配置
要使用哪个版本
IDEA 有两种版本,终极版和社区版。
社区版(以下简称 CE)是 IntelliJ IDEA 的免费开源版本。如果你是一个初学编程的人或者是一个周末战士,这个版本可能最适合你。您可以免费使用 IntelliJ。IDEA CE 支持一些编程语言,比如 Java、Groovy、Kotlin、Scala、Python、Dart、HTML 等。
CE 不是一个残缺的版本,绝对不是;这是一个称职的编辑;也没有角度和附加条件。没有截止日期。你可以免费使用它。永远。
终极版是 IDEA 的付费选项。它做了 CE 所做的一切(当然),还做了更多。它支持更多的语言、更多的框架、更多的工具等等。在一个表格上比较这两个版本要容易得多,所以我们现在就来比较一下。表 1-1 比较了社区版和旗舰版的特性和支持。
表 1-1
IDEA 社区与终极版
| | |终极版
|
社区版
|
| --- | --- | --- | --- |
| 语言支持 | 爪哇 | -好的 | -好的 |
| 绝妙的 | -好的 | -好的 |
| 我的锅 | -好的 | -好的 |
| 缩放(通过插件) | -好的 | -好的 |
| Python 和 Jython(通过插件) | -好的 | -好的 |
| Dart(通过插件) | -好的 | -好的 |
| Rust(通过插件) | -好的 | -好的 |
| HTML、XML、JSON、YAML | -好的 | -好的 |
| XSL,XPath | -好的 | -好的 |
| 降价 | -好的 | -好的 |
| JavaScript,TypeScript | -好的 | |
| 咖啡脚本,动作脚本 | -好的 | |
| 结构化查询语言 | -好的 | |
| CSS,Saas,SCSS,Less,手写笔 | -好的 | |
| Ruby 和 JRuby | -好的 | |
| 服务器端编程语言(Professional Hypertext Preprocessor 的缩写) | -好的 | |
| 去 | -好的 | |
| 框架支持 | 机器人 | -好的 | -好的 |
| 摇摆 | -好的 | -好的 |
| 应用 | -好的 | -好的 |
| Spring (Spring MVC,Spring Boot,Spring Integration,Spring Security 等。) | -好的 | |
| 春云 | -好的 | |
| 爪哇 EE/雅加达 EE (JSF、JAX-RS、CDI、JPA 等。) | -好的 | |
| 冬眠 | -好的 | |
| Micronaut | -好的 | |
| 圣杯 | -好的 | |
| 总重量 | -好的 | |
| 播放(通过插件) | -好的 | |
| 百里香叶,自由标记,速度 | -好的 | |
| AspectJ | -好的 | |
| 阿卡,SSP,Play2 | -好的 | |
| 硒 | -好的 | |
| 反应,原生反应 | -好的 | |
| 角度,角度 JS | -好的 | |
| view . js-检视. js | -好的 | |
| 铁轨上的红宝石 | -好的 | |
| 姜戈,烧瓶,金字塔 | -好的 | |
| Drupal,WordPress,Laravel,Symfony | -好的 | |
| 构建工具 | 专家 | -好的 | -好的 |
| 格拉德尔 | -好的 | -好的 |
| 蚂蚁 | -好的 | -好的 |
| SBT bllop fury | -好的 | -好的 |
| 新公共管理 | -好的 | |
| 网页包 | -好的 | |
| 大口,咕噜 | -好的 | |
| 集成开发工具 | 调试器 | -好的 | -好的 |
| 反编译程序 | -好的 | -好的 |
| 字节码查看器 | -好的 | -好的 |
| 测试覆盖率 | -好的 | -好的 |
| 测试跑步者(JUnit、TestNG、Spock、Cucumber、ScalaTest、spec2 等。) | -好的 | -好的 |
| 嵌入式终端 | -好的 | -好的 |
| 数据库工具/SQL | -好的 | |
| http client(http 客户端) | -好的 | |
| 分析工具 | -好的 | |
| 版本控制 | 吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人吉卜赛人 | -好的 | -好的 |
| 破坏 | -好的 | -好的 |
| 水银的 | -好的 | -好的 |
| Team Foundation Server(通过插件) | -好的 | -好的 |
| 不得已 | -好的 | |
| 部署 | 坞站,坞站复合 | -好的 | -好的 |
| 雄猫 | -好的 | |
| 汤米,汤米 | -好的 | |
| GlassFish | -好的 | |
| 树脂 | -好的 | |
| 码头 | -好的 | |
| 室女宫 | -好的 | |
| JBoss,野猫队 | -好的 | |
| 中间件 | -好的 | |
| WebSphere,自由 | -好的 | |
| 忽必烈忽必烈忽必烈忽必烈忽必烈忽必烈忽必烈忽必烈忽必烈忽必烈 | -好的 | |
| 其他人 | 自定义主题(通过插件) | -好的 | -好的 |
| 问题跟踪集成(YouTrack、JIRA、GitHub、TFS、灯塔、Pivotal Tracker、Redmine、Trac 等。) | -好的 | -好的 |
| 图表(UML,依赖关系) | -好的 | |
| 依存结构矩阵 | -好的 | |
| 检测重复项 | -好的 | |
| 通过 JetBrains 帐户同步设置 | -好的 | |
| 客户支持 | 资源 | 问题跟踪和社区论坛 | 问题跟踪和社区论坛 |
| 支持 | 担保 | 可能的 |
| 许可证 | | 商业 | Opensource,Apache 2.0 |
IDEA 终极版的定价信息位于 www.jetbrains.com/store
。
获取 Java 开发工具包
最好在安装 IDEA 之前安装 Java 开发工具包(JDK)标准版。当您这样做时,IDEA 会自动检测 JDK 安装,这将为您节省一些配置时间。
您有几个选择来使用 JDK,但是两个更受欢迎的选择是
-
甲骨文 JDK——你可以从这里下载安装程序:
www.oracle.com/java/technologies/javase-downloads.html
。 -
open JDK——你可以在这里找到下载链接和安装说明:
https://openjdk.java.net/install/
。
对于这本书,我用了甲骨文 JDK。你不必做同样的事情。如果您喜欢的话,可以使用 OpenJDK。
从我提供的前面的链接中获取适合您的操作系统的安装程序。图 1-1 显示了 JDK 下载的 Oracle 页面——在撰写本文时,JDK 是第 15 版。
图 1-1
Java SE 下载页面
你应该点击“JDK 下载”链接。最好也下载文档。那以后会派上用场的。
Oracle 将要求您同意许可协议,然后才能继续。
在 macOS 上安装
在 macOS 上安装 JDK 非常简单:只需双击下载的 DMG 文件,然后按照提示操作,直到完成。安装程序负责更新系统路径,因此安装后您不需要执行任何进一步的操作。
在 Windows 上安装
在 Windows 上,双击下载的安装程序文件,然后按照提示操作直到完成,就像在 macOS 中一样;但是与 macOS 不同,你需要在系统路径中包含 JDK 工具和二进制文件。您需要知道如何在 Windows 上执行以下操作:
-
在您的 OS 系统路径中包含 Java/bin
-
在系统路径中添加一个类路径定义
请注意,如果您想从 Windows 命令行使用 JDK 工具,只需执行上述步骤。如果你想从一个 like IDEA 中单独使用 JDK,你不需要这么做。
在 Linux 上安装
在 Linux 上安装 Java 有一个 tarball 选项。如果你用的是 RHEL、Fedora 或 CentOS,还有一个 RPM 选项。这些都可以从我前面提到的 Oracle 链接中获得。
或者,您可以使用 PPA 安装 JDK。本指令适用于 Debian 及其衍生产品,例如 Ubuntu、Mint 等。
在终端窗口中,键入以下命令:
sudo add-apt-repository ppa:linuxuprising/java
像往常一样输入您的用户密码。然后,检查更新并安装脚本
sudo apt update
sudo apt install oracle-java15-installer oracle-java15-set-default
当脚本完成时,您的系统上将会安装 JDK 15。
获取和安装 IntelliJ IDEA
在安装 IDEA 之前,请确保您的机器满足推荐的要求——让我们跳过最低硬件要求,因为,我们在骗谁呢,在一台勉强满足最低要求的机器上工作几乎是不可能的。安装 IDEA 的推荐硬件规格如下:
-
RAM–8GB RAM(越多越好)。
-
磁盘–有大量备用空间的固态硬盘。
-
显示器分辨率–全高清(1920 x 1080);尽可能去 4K。你能负担得起的屏幕空间越大越好。
-
OS–最新 64 位版本的 Windows、macOS 或 Linux(例如 Debian、Ubuntu 或 RHEL)。
JetBrains 建议您使用工具箱应用程序来安装 IntelliJ IDEA,但这不是我们在这里将使用的。出于我们的目的,我们将使用独立的安装方法。
让我们从 www.jetbrains.com/idea/download/
得到 CE 安装程序的想法。下载适合您平台的安装程序。您可以在 Windows、macOS 和 Linux 上安装 IDEA。
安装 IntelliJ IDEA
在窗口上
下载安装程序。双击安装程序运行它,然后按照向导完成。在安装过程中,您可以配置以下内容:
-
创建桌面快捷方式。
-
将 IDEA 命令行启动器添加到系统路径中。这很方便,我建议你勾选这个框。
-
将项目 Open Folder 作为项目添加到系统上下文菜单中(当你右击一个文件夹时)。
-
将特定的文件扩展名与 IntelliJ IDEA 相关联,以便双击打开它们。
图 1-2 显示了设置选项。
图 1-2
IntelliJ 安装选项
安装完成后,启动 IntelliJ。
在苹果电脑上
对于 macOS,请遵循以下步骤:
-
下载 DMG 安装程序。
-
双击安装程序来安装它。
-
将 IntelliJ IDEA 应用程序拖放到/应用程序文件夹中。
-
在 Finder 中,进入 /Applications 文件夹,右键点击 IntelliJ IDEA,然后选择“打开”;macOS 可能会询问您是否要打开该应用程序。第一次在 macOS 中启动 IntelliJ 时,可能会出现这种情况。
在 Linux 上
在 Linux 上,二进制安装程序是 tarball 格式的(ideaC-2020.3 . tar . gz);下载吧。然后,将它解压缩到您拥有“执行”权限的文件夹中,如下所示
sudo tar -xzf ideaIU.tar.gz -C /opt
Note
不要在现有 IntelliJ 安装的目录下解压缩 tarball,以免您想要覆盖当前的应用程序——这可能会导致冲突。
接下来,转到解压缩 IntelliJ 的目录,然后运行 idea.sh 文件。
配置 IntelliJ
当您第一次运行 IntelliJ 时,它需要您的一些输入。首先,它会询问你是否想要导入一些你以前对 IntelliJ 的设置——也就是说,如果你以前已经安装了它。图 1-3 显示此提示。
图 1-3
导入 IntelliJ 意见设置
您可以在随后的窗口中选择深色或浅色主题,如图 1-4 所示。
图 1-4
自定义 IntelliJ
您可以继续探索首次启动配置选项,也可以跳过这一步——我就是这么做的。
之后,您将看到 IntelliJ 的欢迎屏幕,如下所示:
关键要点
这里没有太多要注意的,因为我们所做的只是设置;但是如果有什么可以带走的话,我想应该是下面这些:
-
确保在安装 IntelliJ 之前已经安装了 JDK。
-
在安装之前,请确保您的机器符合 IntelliJ 的要求。它不是一个非常重的 IDE(相对于它的同类产品,如 Eclipse 或 NetBeans),但它也不像程序编辑器那样轻(想想 Sublime)。
-
在 Linux 中,确保将 IntelliJ 安装在您拥有“执行”权限的文件夹中。JetBrains 建议将其安装在/opt 文件夹中,但您可以将其安装在任何您喜欢的位置。
二、创建和运行项目
我们将在本章中介绍如下:
-
创建项目
-
建造它
-
运行它
您需要知道的基本任务是在 IntelliJ 中创建、构建和运行项目。这就是我们在本章要做的。
使用 IntelliJ 时,您需要习惯项目的概念,因为如果没有项目结构,您在 IntelliJ 中无法做很多事情。如果您想要构建一个应用程序,您需要创建一个项目并将源代码(和其他资产)添加到该项目中。
构建基本的 Java 项目
如果你还没有启动 IntelliJ,现在是时候了;打开后,您会看到欢迎窗口(如图 2-1 所示)。
图 2-1
欢迎来到 IntelliJ IDEA
突出显示的四个选项允许我们处理一个项目:
-
新项目——这个选项相当简单明了。它将让您从头开始创建一个项目。
-
打开或导入——这将让我们指向一个现有的项目,并让 IntelliJ 从该文件夹中引入所有工件。在此过程中,IntelliJ 将在加载项目时创建一个新的项目配置文件。
-
从 VCS 获得–如果你已经设置了版本控制(我们还没有),你可以使用这个选项从像 GitHub、Bitbucket 或本地回购协议这样的回购协议中加载项目。
-
搜索项目–当你已经创建了几个项目时,在这个打开的屏幕上会有一个很长的列表。您可以使用“搜索项目”功能快速启动项目。
让我们创建一个新项目。选择新建项目。
你会看到新建项目对话框(如图 2-2 )。
图 2-2
新项目
如您所见,IntelliJ 让我们可以使用 Kotlin、Groovy 和 Java 等编程语言来处理各种项目。我们将使用 Java。
如图 2-2 所示,IntelliJ 已经检测到我安装的 JDK;对我来说,是 JDK 15 号。如果您的机器中有多个 JDK 版本,您可以单击 Project SDK 下拉按钮(如图 2-3 所示)来选择您想要使用的 JDK。
图 2-3
新项目,项目 SDK
我将跳过“附加库和框架”部分,因为我现在不需要任何东西,然后单击下一步。
在接下来的窗口中,IntelliJ 允许您从模板创建一个项目(如图 2-4 所示)。
图 2-4
新项目,模板
我会选择一个命令行 App ,然后点击下一个。
在下一个窗口中,我们将输入项目的名称、包和位置,如图 2-5 所示。
图 2-5
项目名称、位置和包
这是一个“Hello World”项目,所以我将使用“Hello”作为项目名称。
项目位置显示 IntelliJ 将存储项目文件的位置。IntelliJ 显示项目文件的默认位置,但是如果您希望将其存储在不同的位置,您可以更改它—如果您希望这样做,请单击省略号(带有三个点的按钮)。
基础包将指定您将在项目中创建的类的名称空间。
对名称、位置和包满意后,单击下一步继续。
IntelliJ 开始创建你的闪亮的新项目,在随后的窗口中,它显示了Main.java文件(如图 2-6 )。
图 2-6
Main.java,与“日积月累”
第一次在 IntelliJ 中创建项目时,会弹出 TOD(每日提示)对话框,并且它会在每次启动 IDE 时一直显示,除非您勾选了不显示提示复选框。我只是把托德留在那里——因为小费给得太多了。您可以点击关闭按钮退出对话框。
现在可以看到我们的主程序了(图 2-7 )。
图 2-7
Main.java
编辑Main.java以匹配清单 2-1 中显示的代码。
package com.workingdev.net;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
Listing 2-1Main.java
完成后,您可以通过进入主菜单栏,然后进入文件 ➤ 全部保存来保存更改,如图 2-8 所示。或者,您可以使用键盘快捷键来保存文件:
图 2-8
全部保存
-
cmd + S
(macOS) -
CTRL + S
(Linux 和 Windows)
IntelliJ 中一个很好的省时工具 Eclipse 中没有——是打开“自动保存”的选项。你可以在首选项(macOS)或者设置(Linux/Windows)中打开这个功能,然后进入外观和行为 ➤ 系统设置 ➤ 自动保存(如图 2-9 )。
图 2-9
首选项|自动保存
下一步是构建项目。你可以从主菜单栏中选择构建 ➤ 构建项目,如图 2-10 所示。
图 2-10
构建项目
当构建完成时,你会注意到在项目工具窗口中会出现一个名为 out 的新橙色文件夹(如图 2-11 )。
图 2-11
项目工具窗口中的 out 文件夹
out 文件夹包含生成的类文件。 out 文件夹被标记为橙色,因为它被排除在项目之外——它毕竟是生成的代码,所以它是有意义的。
您可以用不同的方式标记文件夹。如果你想更深入地探索它,尝试使用 out 文件夹上的上下文菜单,然后选择标记目录(如图 2-12 )。
图 2-12
将目录标记为
你现在不需要做任何改变。我只是想指出 IntelliJ 在标记文件夹方面能做些什么。如果您向项目中添加一些临时资源,但这些资源不一定是项目的一部分(如输出目录),或者当您创建测试根文件夹时(单元测试时),这可能会很方便。
下一步是运行程序。进入主菜单栏,然后进入运行 ➤ 运行主,如图 2-13 所示。
图 2-13
奔跑
IDE 底部弹出输出窗口(如图 2-14 所示)并打印我们程序的结果。
图 2-14
Hello World 输出
给你。这就是如何在 IntelliJ 中创建和运行 Java 项目。
建设大型项目
在这一节中,我将向您展示 IntelliJ 如何处理大型项目。你不必跟着来。事实上,我建议您不要这样做,因为我们还没有能力解决导入重要项目所带来的问题。
我要做的是从 GitHub home repo 下载 IntelliJ IDEA CE 的源代码(如图 2-15 ) https://github.com/JetBrains/intellij-community
。这个项目是巨大的。已经分叉了三千八百次;它有 320 个分支机构和 614 个贡献者。这不是一个微不足道的项目。
图 2-15
IntelliJ 在 GitHub 上休息
我将通过点击“代码”按钮下载项目(如图 2-16 )。我去拿压缩文件。
图 2-16
下载 ZIP
我将解压压缩文件,然后在 IntelliJ 中打开它。“Hello World”项目仍然在我的机器中打开,所以我将进入主菜单栏,然后进入文件 ➤ 打开,然后指向我解压缩压缩文件的目录。
IntelliJ 将加载项目的所有工件并创建新的配置。在这个过程中,我需要解决一些冲突,如版本,SDK 设置等。;但是一旦完成,来自 GitHub 的 IntelliJ 项目将被加载。
我将构建项目,就像我们如何构建“Hello World”项目一样。IntelliJ 忙于构建项目(如图 2-17 所示)。
图 2-17
IntelliJ 项目加载到 IntelliJ 中
这不会是一个短暂的过程。这要花一点时间,足够我喝点咖啡,吃点快餐了。
当它最终完成时,我将运行这个项目, et voila ,我将再次看到 IntelliJ 的欢迎窗口——我不会再向您展示它了,因为您已经看过了。
关键要点
-
从头开始创建项目非常简单。您可以从“欢迎”窗口执行此操作。
-
您可以将现有项目加载到 IntelliJ 中;只需使用欢迎窗口中的打开选项,并指向现有项目的文件夹。
-
IntelliJ 是一个非常有能力的 IDE 它可以处理大型项目——这就是我向您展示如何从 IntelliJ 内部构建 IntelliJ IDE 本身的原因。如果 IntelliJ 能处理这么大的项目,我打赌它也能处理你的项目。
三、项目文件
我们将在本章中介绍如下:
-
IntelliJ 模块
-
那个。创意文件夹
-
out 文件夹
-
外部库
在前一章中,我们创建了一个小项目。内容不多,但它让我们体验了 IntelliJ 中的项目创建、编译和执行。在这一章中,我们将更仔细地看看组成 IntelliJ 项目的文件。
大多数足够先进的 ide,除了简单编辑源文件之外,还会生成包含配置、状态、首选项等的专有文件。IntelliJ 也不例外。
本章将着眼于 IntelliJ 作为项目的一部分生成的一些文件。
iml 文件
这包含基本的模块信息。IntelliJ 中的模块不同于 Java 模块(在 Java 9 中引入)。IntelliJ 模块是一个独立的功能块,可以在 IDE 中独立运行、测试和调试。一个项目可能包含不止一个模块,它可能包含诸如源代码、构建脚本、单元测试、部署描述符等内容。iml 文件描述了一个模块。
图 3-1 显示了示例 iml 文件的内容。
图 3-1
显示 iml 文件的小项目
如您所见,这个项目中只有一个模块。它是随着项目自动创建的。您可以根据需要向项目中添加模块。
项目中的每个模块可以使用特定的 SDK,甚至可以根据项目设置继承一个 SDK。清单 3-1 显示了我们的(默认)iml 文件的内容。
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
Listing 3-1test.iml
那个。创意文件夹
。idea 文件夹是应用于整个项目的配置文件的集合,不管它包含多少模块。这是每个项目的根本。图 3-2 显示了一个带有的项目。项目工具窗口中展开的 idea 文件夹。
图 3-2
的内容。创意文件夹
当您更改项目设置或 IDE 设置时,这些更改将反映在中的一个文件中。创意文件夹。如果您更改了 JDK 设置、将模块添加到项目、更改了编码等。这些改变会使它成为这些文件中的一个。最好不要手动编辑这些文件。
如果这是您第一次使用 IntelliJ,您可能想知道是否应该包含。源代码管理中的 idea 文件夹。JetBrains 建议所有的内容。idea 文件夹,保存一个,放在源码控制中。您不应该签入的是 workspace.xml ,因为它包含您对项目的个人偏好;只是给你的。
SRC 文件夹
src 文件夹是我们完成大部分工作的地方。您可能已经猜到,src 是源代码的缩写,就像源代码一样。图 3-3 显示了编辑窗口中显示的源代码。
图 3-3
Main.java 显示在主编辑窗口中。
我们的小示例项目只有一个 Java 源文件,它在 com 下。公司文件夹,如图 3-3 所示。IntelliJ 将源文件放在与包声明同名的文件夹下。
当您添加代码(在同一个包中)时,您会在相同的文件夹名称下看到它们。当您添加一个代码时,不在同一个包中,一个新的文件夹(带有新包声明的名称)将被添加到 src 文件夹中。
Out 文件夹
当您运行或生成代码时,另一个文件夹将被添加到项目的根目录中。那就是 out 文件夹(如图 3-4 )。
图 3-4
out 文件夹的内容
out 文件夹包含可执行的 Java 文件(字节码)。如果你点击 Main.class 文件尝试查看其内容,IntelliJ 不会打开类文件的内容;而是会提示你是否要反编译(如图 3-5 )。
图 3-5
JetBrains 反编译程序
反编译器是一个很有价值的工具,尤其是当你不能访问可执行文件的源程序时。这里有一点来自 JetBrains 的警告,因为如你所知,反编译程序的使用是一个灰色地带。反编译器有合法的用途,也有不正当的原因。不管怎样,为了我们的好奇心,让我们反编译一下,好吗?毕竟这是我们自己的项目。要使用反编译器,必须点击“接受”(图 3-5 )。
图 3-6 显示了反编译后的 Main.class 。
图 3-6
反编译 Main.class
外部库
在“外部库”文件夹中,您可以看到项目所依赖的所有库。我们创建了一个简单的项目,所以除了 JDK 图书馆之外,现在没什么可看的(如图 3-7 所示)。
图 3-7
外部库文件夹的内容
关键要点
-
IntelliJ 将其项目和 IDE 设置保存在内的 XML 文件中。创意文件夹。当您对项目、IDE 或您的环境进行更改时,这些更改会保存在中的文件中。创意文件夹。
-
JetBrains 建议我们保留。源代码管理中的 idea 文件夹,除了 workspace.xml 。你应该把它放进去。 gitignore 文件(如果你使用 Git 的话)。
-
IntelliJ 有一个内置的反编译器,可以用来查看反编译类的源代码。
四、IDE 工具
在本章中,我们将介绍以下内容:
-
项目工具窗口
-
导航栏
-
结构工具窗口
-
临时文件
-
待办事项
-
问题工具窗口
-
末端的
-
主要编辑
IntelliJ 是一个健壮的 IDE。虽然它很快,但它并不完全是轻量级的——这是有充分理由的。它的功能非常丰富。在这一章中,我们将看看一些最常用的 IntelliJ 工具。
IDE
让我们先熟悉一下 IDE。图 4-1 显示了你可能最常使用的 IDE 的一些部分。
图 4-1
IntelliJ IDEA(项目已打开)
| -什么 | **主菜单栏**–这是导航 IntelliJ 的主要方式,但这里的大多数项目都有键盘快捷键,所以知道这些快捷键是有好处的,尤其是对于你经常使用的命令。JetBrains 在其网站上维护了一个页面,列出了最常用的键盘快捷键;你应该把它做成书签——或者更好,把它打印出来贴在你的笔记本上,别在你的公告板上,等等。下面是链接: [`www.jetbrains.com/help/idea/mastering-keyboard-shortcuts.html`](http://www.jetbrains.com/help/idea/mastering-keyboard-shortcuts.html) 。 | | ➋ | **导航条**–该导航条是动态的。当你进行一项操作时,它会在这里留下你的脚印,就像一些网站上的面包屑一样。如果你想追溯你的步骤,这是非常有用的。 | | ➌ | **工具栏**–在这里你可以找到最常见的开发任务,例如,运行应用程序、调试应用程序、搜索、设置等。 | | -你好 | **编辑窗口**——节目的明星。这是你做编码工作的地方。当您启动一个文件(从项目工具窗口)时,IntelliJ 会在这里打开它进行编辑。 | | ➎ | **项目工具窗口**–您可以在这里浏览您的项目。您可以从该窗口启动任何项目文件。 | | ➏ | **工具窗口栏**–它沿着 IDE 的周边运行。如您所见,它包含了启动特定工具窗口所需的各个按钮,如收藏夹、结构、问题、待办事项、终端等。 | | -好的 | **显示/隐藏工具窗口**–显示或隐藏工具窗口栏。这是个开关。 |项目工具窗口
在主编辑器窗口旁边,项目工具窗口可能是您花费大量时间的地方。此窗口显示项目的各种视图。它还允许您在项目中添加、移除或重新定位项目。项目工具窗口是将项目文件启动到主编辑器窗口的主要方式;双击它,它就会弹出来供编辑。
图 4-2 显示了带有默认项目视图的项目工具窗口。
图 4-2
项目工具窗口
如果主编辑器窗口需要更多的屏幕空间,可以通过点击工具窗口栏上的按钮隐藏项目工具窗口(如图 4-3 )。
图 4-3
项目工具窗口,隐藏
默认情况下,项目工具窗口使用项目视图显示文件;这个视图向我们展示了项目中的所有文件——甚至是那些与我们的代码不直接相关的文件,例如,。想法文件、 iml 文件等。您可以通过点击项目视图下拉菜单(如图 4-4 所示)然后选择“包”来改变这个视图,只显示与我们的应用程序代码直接相关的文件
图 4-4
切换到包视图
图 4-5 显示了“包”视图上的项目工具窗口。现在我们只能看到代码包中的代码——其他什么也看不到。
图 4-5
项目工具窗口,在包视图中
当您单击下拉菜单来更改项目工具窗口的视角时,您可能已经注意到还有其他选项,如打开文件、测试、划痕和控制台。
项目工具窗口视图的其他选项(简要)解释如下:
-
如果您创建了任何单元测试类,那么当您选择这个视图时,它们就会显示出来。
-
打开的文件–显示主编辑器中所有打开的文件。
-
scratch and Consoles–显示你所有的 scratch 文件。
结构工具窗口
项目工具窗口的正下方是结构窗口。正如您可能已经从它的名字中猜到的,它显示了类(和接口)的结构。
结构窗口的内容反映了项目工具窗口中当前选中的类或接口的结构,如图 4-6 所示。
图 4-6
结构工具窗口
结构窗口显示所选类的所有字段(成员变量)、方法、lambdas 和属性。它甚至会告诉你类成员是否被继承。
结构窗口是导航您的类的有用工具,尤其是当您的类变得更加复杂时。
导航栏
导航栏未被充分重视。许多程序员认为这个工具只是一个美化了的面包屑——好吧,它确实是某种面包屑机制,但不仅仅如此。您可以通过导航栏真正导航整个项目,就像您使用项目工具窗口导航一样。
面包屑中的每个项目都是可导航的;如图 4-7 所示,当我们点击“套接字编程”(项目名称)上的面包屑时,它会显示项目上的其他文件和文件夹——就像在项目工具窗口中一样。
图 4-7
导航栏显示项目级别的下拉列表。
图 4-8 显示了显示包装内容的导航栏。
图 4-8
显示包级别下拉列表的导航栏
图 4-9 显示了显示类成员的导航栏,就像在结构窗口中一样。
图 4-9
导航栏显示课程级别的下拉列表
临时文件
这个名字泄露了秘密。草稿文件可让您为项目创建草稿。这是一种写下东西或跟踪事情的便捷方式,但是您不确定是否希望这些代码成为项目的一部分。
您可以使用“Scratches and Consoles”(在项目工具窗口中)上的上下文菜单创建一个 scratch 文件;点击新建 ➤ 暂存文件(如图 4-10 )。
图 4-10
创建新的暂存文件
在随后的弹出窗口中,选择您想要创建的暂存文件类型;您可以从各种类型中进行选择,例如,Java 文件、HTML、JSON 等。(如图 4-11 所示)。
图 4-11
新暂存文件
您可以编译 Java 临时文件(并运行它们),就像您编译并运行实际上是项目一部分的 Java 文件一样;参见图 4-12 。
图 4-12
暂存文件,编译并运行
您可以很容易地更改暂存文件的文件格式;只需右键单击暂存文件,选择“覆盖文件类型”,然后选择新的文件类型。
待办事项
待办事项是对你自己(或团队其他成员)的指示。这是一个提示,提醒你做特定的事情或者在特定的类上实现特定的特性。
你可能认为这没什么大不了的;毕竟所有的编程编辑都可以这么做吧?是也不是。是的,因为所有的编辑器都允许你写待办事项提醒。只需在 TODO 项前面加上注释字符,然后写下 TODO。就像这样:
// TODO Write a thread app, do the accepting and responding of msgs there
后面跟单词 TODO 的单行注释应该可以达到这个目的。这没什么,但 IntelliJ 的亮点在于它如何将你所有的待办事项收集在一个地方。
点击待办事项工具窗口(如图 4-13 所示)查看整个项目的所有待办事项。
图 4-13
整个窗口
“待办事项”窗口显示分散在项目文件中的所有待办事项。此外,如果双击任何 TODO 项,IntelliJ 将在主编辑器中打开包含 TODO 注释的文件。
问题
“问题工具”窗口显示整个项目中的所有问题和警告项。起初,您可能看不到问题工具窗口的价值,因为 IntelliJ 做了一项出色的工作,无论何时您搞砸了一个语法,它都会告诉您(似乎就在您的面前)——您会看到红色的卷线。但是这个窗口真正的亮点是在警告方面。在 IntelliJ 中,警告并不重要。只有当你的鼠标停留在一行代码(IntelliJ 认为它可以改进)上时,你才会意识到它们,然后你会看到一个黄色的灯泡——如图 4-14 所示。
图 4-14
IntelliJ 警告
否则,你甚至不会意识到这些警告。
“问题工具”窗口显示项目中的所有错误和警告。所以,如果你想全部看到,只需点击工具窗口栏中的“问题”按钮(如图 4-15 )。
图 4-15
问题工具窗口
单击问题工具窗口中的任何警告(或问题)项,会在主编辑器窗口中显示相关文件。
末端的
“终端工具”窗口打开时,是一个可以在 IntelliJ 中使用的实际终端。许多程序员使用这个工具,因为在键盘上打字仍然比用鼠标搜索和啄快。如果您非常熟悉 CLI 命令,您会喜欢终端窗口。它在 IDE 的底部弹出(并隐藏),如图 4-16 所示。
图 4-16
终端窗口
当您打开终端窗口时,IntelliJ 会直接将您带到项目目录。没有必要 CD 到~/idea projects/name your project——仅仅是为了这个行为,我就不再使用我的原生终端工具了。我只使用 IntelliJ 中的终端。
您可能想要使用“终端”窗口的一些原因:
-
如果你是一个命令行忍者,你喜欢做你的 Git 推送,存储,提交,添加等。,但是您不想离开 IDE,那么终端就非常适合您。
-
您可能需要在 Maven 或 Gradle 上运行一些命令。
-
你运行的是 MongoDB (mongod 和 mongo)。您可以在 IDE 中创建多个终端会话,这非常适合这些任务。
主编辑器窗口
主编辑器窗口占据了最大的屏幕空间,这是创建和编辑代码的地方。
您可能不需要使用主编辑器窗口的说明;毕竟很直观。您可以在使用它的过程中了解它的功能,但我还是想指出一些事情。首先,主编辑器允许您折叠代码的各个部分。当你点击房屋形状的五边形时(如图 4-17 所示),代码的各个部分将会折叠。如果你点击同一个五边形,它会展开。当你审计你的代码时,这是一个很好的工具。
图 4-17
代码折叠
接下来,当你正在编辑一个有 runnable main 方法的类时,编辑器栏上的 Run 按钮就会出现(如图 4-18 所示)。单击此按钮将允许您运行您的类,就像单击工具栏上的运行按钮一样。
图 4-18
编辑器栏上的运行按钮
接下来是编辑窗口右上角的警告图标(如图 4-19 )。IntelliJ 显示项目中发现的所有问题的摘要。单击警告摘要会打开问题工具窗口。
图 4-19
右上角的警告图标
接下来是 GUI 编辑器。你可能会使用 GUI 组件、Android 应用程序(如图 4-20 所示)或 JavaFX 应用程序(如图 4-21 所示)来处理项目。不管是什么情况,IntelliJ 都会保护你。它有所见即所得的能力来完成工作。
图 4-21
JavaFX 场景生成器
图 4-20
Android 项目
关键要点
-
IntelliJ 不是一个简单的程序编辑器。这是一个全面的集成开发环境,加载了许多有用的功能。
-
在 IntelliJ 中导航项目文件的方法不止一种。导航项目文件的主要方式是通过项目工具窗口,但也可以通过导航栏来完成。
-
IntelliJ 的 TODO 功能简单易用;只需写一行注释,后跟单词 TODO,就可以开始了。当您单击工具窗口栏中的待办事项工具窗口时,可以看到所有待办事项。
-
用 IntelliJ 的集成终端做一些 CLI 杂技;这里不需要 cmd、Terminal、iTerm 或 Terminator。
-
主编辑器窗口具有 GUI 编辑功能;当您使用 Android 项目或 JavaFX 项目时,这将非常方便。
五、代码导航和生成
在本章中,我们将介绍以下内容:
-
如何使用 IntelliJ 中的“到处搜索”功能
-
如何使用键盘快捷键进入任何 IDE 操作
-
如何在没有狩猎和北平的情况下寻找档案
-
如何生成样板代码
你见过谁信誓旦旦地认为 Vim 是最好的编辑器吗?你有吗?你知道他们为什么这么说吗?其中一个原因,我认为,是因为有了 Vim,你不用鼠标来导航。都是键盘。你的手永远不会离开键盘——对一些人来说,这让他们处于一种流畅的状态。
你可以用 IntelliJ 做类似的事情。如果你想尝试双手(几乎)不离开键盘的工作流程,这一章就是为你准备的。
航行
你可能想知道为什么我们专门为代码导航写了一章。“当然,我知道如何浏览我的代码,”你告诉自己。“打开项目工具窗口,向下钻取到包和层次结构,然后双击打开— et voila !”
如果是一个小项目,或者当编码速度并不重要时,你可以通过搜索和啄文件、类、变量和方法来获得——任何以编码为生的人都不会告诉你速度不重要。这总是很重要——但是当你不再编写“hello world”项目时,发展你的编码习惯将是一件大事。
当你检查你的编码过程(我指的是你自己的编码过程)时,你会发现至少有一半的时间,你并不是真的在敲东西——你实际上是在做更多的导航而不是敲代码。
如果你在狩猎和啄食,你正在失去宝贵的时间。有更快的方法来得到你的代码,这一节就是关于这个的。
到处搜索
你在 IntelliJ 中需要的最重要的键盘快捷键实际上在 IDE 的后台开始屏幕上(如图 5-1 所示);然而,这也是最容易被忽视的。大多数人不会关注开始屏幕;我们如此渴望打开源文件并开始输入。
图 5-1
IntelliJ 的开始屏幕
开始屏幕提示为我们提供了一些漂亮的键盘快捷键,但是让我们从搜索所有地方快捷键开始。
您可以通过快速连续按下 Shift 键两次来激活到处搜索对话框(图 5-2 显示了到处搜索对话框)。
图 5-2
到处搜索
您可以开始在搜索栏中键入内容,开始看到一些结果。您可以通过名称找到项目中或项目外的任何项。您可以从单个入口点搜索文件、操作、类、符号、设置、UI 元素和 Git 中的任何东西。如果你还记得你的正则表达式,你可以用它们在搜索所有地方对话框中查找项目。
对话框中有几个选项卡(类、文件、符号、动作和全部)。默认情况下,您被放置在 All 选项卡上,但是您可以通过用鼠标选择它们来切换选项卡。
现在您可能已经知道,当您想要搜索类时,使用 Classes 选项卡,当您在解决方案中查找文件时,使用 Files ,当您搜索 IDE 操作时,使用 Actions ,当您查找类名、变量、常量和方法名时,使用符号。
当您在解决方案中查找文件而不是动作时, All 选项卡更有用。当您使用这个搜索工具时,请注意对话框是如何划分的,这样您就可以掌握它的窍门了。
顺便说一下,您一定注意到了“搜索所有地方”对话框中的勾号框,上面写着“包括非项目项”当您检查它时,您可以在 Java 文档中搜索非项目项,如类(如果您下载了它)。搜索非项目项目的最快方法是使用双 Shift 键盘快捷键,然后再次按下双 Shift 将搜索扩展到非项目项目。
查找操作
动作是指 IDE 动作,如打开终端、构建项目、创建文件等。您可以通过执行以下任一操作来执行操作:
-
通过主菜单栏,然后浏览子菜单项,直到找到您需要的动作。
-
使用上下文菜单–如果你知道在哪里点击右键,你可以得到你需要的动作。
-
点击工具栏上的按钮–工具栏上会显示一些最常见的操作,如运行、调试、停止等。
-
使用键盘快捷键——这是最快的,但这也意味着你需要记住这个快捷键。你也许可以对那些你经常使用的动作这样做,但是你不能对所有的动作都这样做。
-
使用 到处搜索 对话框然后准备行动。开始键入操作的名称,然后按 ENTER。这是第二种最快的行动方式。
例如,如果您想要启动一个终端会话(在 IntelliJ 中),您可以使用选项+ F12 (在 macOS 上)或 Alt + F12 (在 Linux 和 Windows 上)。如果你不记得键盘快捷键,你可以使用到处搜索对话框,然后选择动作。或者,如果你不想让你的手指离开键盘,你也可以使用 Shift + cmd + A 快捷键(对于 macOS)或者 Shift + CTRL + A (对于 Linux 和 Windows)来启动到处搜索对话框并直接进入动作标签。
图 5-3 显示了我们搜索终端动作时的动作对话框。
图 5-3
行动
这个对话框向我们展示了一些关于终端操作的信息。我们可以看到它的键盘快捷键,也可以看到这个动作在主菜单栏上的位置。此时,您只需按下 ENTER 键即可启动该操作。
打开文件
如果您一直使用项目工具窗口打开文件,您会很高兴知道有更快的方法来访问您的文件。
图 5-4 所示的项目很小,但足以演示如何使用项目工具窗口搜索文件。将鼠标放在项目工具窗口下箭头的右边(如图 5-4 ,然后开始输入(如图 5-5 )。
图 5-5
在项目工具窗口中搜索文件
图 5-4
单击项目工具窗口旁边的
但是,只有当文件在项目工具窗口中可见时,此技术才有效。如果不是,例如当 src 文件夹被折叠时,这种搜索方法就会失败(如图 5-6 所示)。嗯,无论如何,你都可以使用到处搜索对话框查找文件。
图 5-6
带有折叠 src 文件夹的项目工具窗口
开放课程
在命名 Java 源文件时,最好用类名来命名文件。这样,当您查看项目工具窗口时,只需查看实际的源文件,就可以知道类文件在哪里。如果你遵循了这个建议,那么对你有好处。如果你没有,IntelliJ 支持你是件好事。在 IntelliJ 中搜索类定义非常容易;只要在 macOS 上按下 cmd + O (大写字母 O,不是零),在 Windows 和 Linux 上按下 CTRL + N ,然后开始输入。
图 5-7 显示了搜索类别对话框。
图 5-7
搜索课程
转到符号
为了完成我们在到处搜索对话框选项卡上的讨论,让我们看看符号。当你在寻找变量、方法名和常量时,到处搜索对话框的符号选项卡是一个不错的选择。
转到符号的快捷键在 macOS 上是 option + cmd + O (大写字母 O)在 Windows 和 Linux 上是 Shift + CTRL + Alt + N 。
图 5-8 显示了运行中的转到符号对话框。
图 5-8
标志
最近的更改和文件
您可能经常需要的另一个有用的 IDE 快捷方式是如何查看最近更改的文件,以及通常项目中最近的更改。
要查看您最近处理过的文件,请使用 cmd + E 快捷键(macOS)或CTRL+E(Windows 和 Linux)。图 5-9 显示最近的文件对话框。
图 5-9
最近的文件
当你有健忘的时候,这个对话框很有用,你可以试着记起你正在处理的源文件。这是一个伟大的记忆慢跑者。请注意,它不仅会告诉您最近接触过的文件;它还会告诉您最近的一些操作(在对话框的左侧)。
另一个你可以使用的记忆点动器是最近 地点对话框(如图 5-10 )。可以使用 Shift + cmd + E (macOS)或者 Shift + CTRL + E (Windows 和 Linux)来激活。
图 5-10
最近位置
如果你想查看你最近在项目中所做的所有更改的列表,例如,创建一个新文件,使用快捷键 Shift + cmd + C (macOS)或 Shift + Alt + C (Windows 和 Linux)。图 5-11 显示最近变更对话框列表。
图 5-11
最近的变化
该对话框显示了所做的更改(在本例中是创建一个文件)以及更改的时间。列表上的项目是可点击的。它就像指向已更改文件的超链接,因此您只需单击它们就可以快速查看或编辑它们。
开放目标类型
有时候,你会遇到一些你不太熟悉的类型。在这些时候,快速浏览一下文档(或实际的代码实现)会非常有用。IntelliJ 可以让你做到这一点。将光标放在您想要调查的类型上,如图 5-12 所示,我将光标放在雇员类型上。然后用 cmd + B (macOS)或者 CTRL + B (Linux 和 Windows)打开定义了类型的源文件。
图 5-12
程序员源文件
IntelliJ 启动定义了类型的源文件(如图 5-13 所示)。
图 5-13
员工源文件
您不局限于解决方案中的文件;您也可以查看标准 Java 库中的文件。图 5-14 显示我的光标位于螺纹型;按下 cmd + B 快速将我带到线程类的定义(如图 5-15 所示)。
图 5-15
线程类别定义
图 5-14
主程序源文件
cmd + B 快捷方式不仅限于类型——它也适用于方法。当您在方法上使用该快捷方式时,IDE 将向您显示该方法在解决方案中的所有用法(如图 5-16 所示)。
图 5-16
解决方案中方法的用法
窥视定义
查看定义类似于打开目标类型(我们在上一节中讨论过),但是与打开目标类型不同的是,查看定义不启动或打开文件。相反,它会显示一个弹出对话框,您可以在其中看到类型的定义。
要检查这一点,将光标放在您想要查看的类型上,就像我们在中所做的那样打开目标类型,然后按下按键 option + space (macOS)或 Shift + CTRL + I (Windows 和 Linux)。示例如图 5-17 所示。
图 5-17
窥视雇员类型的定义
显示成员
你把成员变量放在哪里?你是在类开始的时候,在所有方法之前一次性定义它们,还是在接近使用点的时候定义它们?以一个真正的编码惯例的名义发动了一场激烈的战争,但是这已经无关紧要了,因为像 IntelliJ 这样的 ide 可以在一个简洁的窗口中显示所有的类成员。
至少有两种方法可以看到该类的所有成员。第一种是通过使用 cmd + F12 (macOS)或者 CTRL + F12 (Windows 和 Linux);样品如图 5-18 所示。
图 5-18
显示成员
查看成员的另一种方法是显示结构窗口(图 5-19);使用 cmd + 7 (macOS)或者 Alt + 7 (Windows 和 Linux)。
图 5-19
结构窗口
使用 cmd + 7 来切换结构窗口的可见性,这样你就可以在不需要的时候把它移开。
查看类层次结构
IntelliJ 的另一个简洁的特性允许您在主编辑器中查看当前所选类的类层次结构。只需使用快捷键 CTRL + H (这是 macOS、Linux 和 Windows 的按键)来显示类层次结构窗口——如图 5-20 所示。
图 5-20
显示类层次结构
这是我想向您展示的关于代码导航的最后一个技巧。下一站,代码生成。
代码生成
IntelliJ 的另一个节省时间的特性是代码生成器;它的名字恰如其分,因为它确实做了你认为它会做的事情——它生成代码。
激活代码生成对话框的快捷键是 cmd + N (macOS)或者 Alt + Insert (Linux 和 Windows)。图 5-21 显示了运行中的代码生成对话框。
图 5-21
代码生成对话框
如您所见,您并不局限于构造函数生成。我将让你来试验其他的选择。
我想展示的下一个例子是如何为 getters 和 setters 生成代码——这是 Java 编程中非常常见的任务。
图 5-21 显示了带有两个成员变量的类程序员, mLastname 和 mFirstname 。显示代码生成对话框,然后选择 Getter 和 Setter ,如图 5-22 所示。
图 5-22
生成 getters 和 setters
IntelliJ 显示所有自动检测的成员变量(如图 5-23 所示)。您可以选择想要为其生成 getters 和 setters 的所有成员,您可以在这里进行多项选择。
图 5-23
选择字段以生成 getters 和 setters
单击确定按钮生成代码。清单 5-1 展示了我们的程序员类,它为 mFirstname 和 mLastname 自动生成了 getters 和 setters。
public class Programmer implements Employee{
String mLastname;
String mFirstname;
public String getmLastname() {
return mLastname;
}
public void setmLastname(String mLastname) {
this.mLastname = mLastname;
}
public String getmFirstname() {
return mFirstname;
}
public void setmFirstname(String mFirstname) {
this.mFirstname = mFirstname;
}
@Override
public void work() {
}
}
Listing 5-1Class Programmer with Generated Getters and Setters
这已经很不错了。任何能让我们节省击键次数的东西都是好东西。我猜你可能只对这个例子有一点挑剔;方法命名不正确。你可能更喜欢称为 setLastname() 而不是 setmLastname(),不是吗?让我们解决这个问题。
转到 IntelliJ 的偏好设置—使用快捷键 cmd +,macOS 使用(逗号)。对于 Linux 和 Windows 来说是 CTRL + Alt + S ,然后进入代码风格➤ Java ➤代码生成,如图 5-24 所示。
图 5-24
首选项➤代码风格➤ Java ➤代码生成
在字段名前缀中,告诉 IntelliJ 如何给成员变量加前缀。在我的例子中,我用字母 m 作为成员变量的前缀,因此, mLastname 作为姓氏变量。
单击 Apply 或 OK 按钮保存更改,然后再次为 mFirstname 和 mLastname 生成 getters 和 setters。
清单 5-2 显示了重新生成的程序员类。
public class Programmer implements Employee{
String mLastname;
String mFirstname;
public String getLastname() {
return mLastname;
}
public void setLastname(String lastname) {
mLastname = lastname;
}
public String getFirstname() {
return mFirstname;
}
public void setFirstname(String firstname) {
mFirstname = firstname;
}
@Override
public void work() {
}
}
Listing 5-2Programmer Class with Autogenerated Getters and Setters
这还差不多!
关键要点
-
所有 IDE 操作都可以通过主菜单栏来执行,但是激活这些操作的最快方式是通过键盘快捷键。
-
在 IntelliJ 中激活一个动作的第二种最快方法是使用 cmd + A (macOS)或 Shift + CTRL + A (Windows 和 Linux)搜索动作。
-
如果你能记住一些快捷键,你将会节省很多时间,但是如果你只能记住一个快捷键,那就让它变成双 Shift 吧。只需连续按下 Shift 键两次,就可以打开“到处搜索”对话框。
六、检查和意图
在本章中,我们将介绍以下内容:
-
代码检查
-
意图
你使用 IntelliJ 已经有一段时间了。我很确定你已经看到了灯泡(红色和黄色)、带有感叹号的黄色三角形和下面带有一条曲线的绿色复选标记——这些是 IntelliJ 用来告诉我们代码有问题的图标。他们被称为检查图标。我们将在本章中讨论它们。
代码检查
IntelliJ IDEA 是智能的(双关语);它比你更了解你的代码。当你打字时,它在后台努力工作,试图看到你弄糟了代码的哪些部分;在代码被修改的地方,IntelliJ 会给出警告信号——请注意,这一切甚至发生在你编译代码之前。如果 IDE 是哑的,它就不会被称为 IntelliJ。名不虚传。
代码检查是 IDE 的一项功能,它可以扫描、检测和纠正项目中的异常代码,甚至可以在编译之前进行。IDE 可以发现并突出显示各种问题。它可以定位死代码,发现拼写问题(比您希望的更多),并改进整体代码结构。
IntelliJ 可以发现的问题从良性到严重都有,比如尾部的分号(如图 6-1 所示)。黄色灯泡表示警告;它们是良性的,因为它们不会阻止你编译,但是 IntelliJ 警告你,因为代码不是最佳的。
图 6-1
IntelliJ 标记尾部分号
其他时候,你会看到一个红色的灯泡(如图 6-2 中的灯泡)。
图 6-2
红色灯泡,表示有错误
红色灯泡是错误标志。您需要对有问题的代码进行更改,以免您的项目无法编译。
解决检查问题
最容易处理的检查是那些相当明显的检查,例如,不可及的语句,如图 6-3 所示。
图 6-3
不可达语句
最后一条 println() 语句下面的红色曲线清楚地表明您的代码有问题。假设你按下 option + ENTER (macOS)或者 Alt + ENTER (Windows 和 Linux),IntelliJ 的快速修复就开始了。IDE 向您展示您可能想要采取的检查操作,以便您可以解决问题,如图 6-4 所示。
图 6-4
检查行动
在我们的例子中,操作很简单;只需删除不可及的语句,如果你选择,问题立即消失——但这是显而易见的;当然,您可以看到 println() 是无法到达的。你不需要为此检查。让我们试试另一个。
看看你能不能认出这个。在图 6-5 的第 6 行,我给打了个电话。 AnotherMethod() 和 IntelliJ 通过用红色波浪线给这个的调用加下划线来升起一面旗帜。你能说出原因吗?
图 6-5
对另一个方法()的非静态调用的检查操作
在我们的例子中很容易发现错误,因为它是一段很短的代码,但是当您的源文件已经有几百行长时,很容易忘记 AnotherMethod() 是静态的;这也是为什么把叫做的原因。 另一种方法()进行标记。但是不要担心,让我们看看检查行动提供了什么。再次执行选项+ ENTER (或者如果您在 Linux 或 Windows 上,执行 Alt + ENTER )来显示检查操作。
图 6-6
检验行动选项
检查中有几个建议:
-
使主要的,而不是静态的-这是不可行的。主方法必须是静态的。有时候,检查操作提供的选项没有帮助(也不正确),这就是其中之一。
-
进入静态主程序。AnotherMethod()via class main program reference——这只是一种花哨的说法,“删除第 6 行中的 this 关键字,并简单地调用 another method(),而不使用自引用。”这将解决我们的问题。
-
清理代码–这将做与第二个(前面的)选项完全相同的事情。它将简单地删除没有自引用的调用 AnotherMethod()。大多数时候,这是正确的选择。所以,让我们选择这个,清单 6-1 显示了结果代码。
public class MainProgram {
public static void main(String[] args) {
NumberGenerator numgen = new NumberGenerator();
this.AnotherMethod();
}
static void AnotherMethod() {
System.out.println("another method");
}
}
Listing 6-1The resulting code
大多数时候,检查操作非常简单,就像在代码中使用一个类型而没有先停下来导入它一样——为什么要这么麻烦呢?只需要一个 Alt + ENTER 就可以了(见图 6-7 )。
图 6-7
使用检查操作导入类
检验代码
IntelliJ 在我们键入时标记我们的错误;如果您希望在运行过程中得到次优代码的警告,这是非常方便的。IntelliJ 在后台实际检查整个项目的错误和警告。
IDE 会让您在浏览当前行时注意到错误(或警告),但是如果您想知道整个文件的错误/警告,您可以通过单击右侧的检查图标来做到这一点——它是编辑器右上角的小部件,显示当前文件中的问题数量(及其严重性)。如图 6-8 所示。
图 6-8
检查图标
如果点击 inspection widget,IntelliJ 会显示问题工具窗口(如图 6-9 )。
图 6-9
显示问题工具窗口的主编辑器
“问题工具”窗口显示当前文件中所有问题的综合列表。你可以通过简单地点击问题列表上的每一项来逐一查看它们。
当您单击每个项目时,IDE 会将光标移动到发现问题的特定行;然后,您可以使用 option + ENTER (对于 Windows 和 Linux 为 Alt + ENTER)来选择一个修复(如图 6-10 )。
图 6-10
修复无法实现的语句
或者,您可以在问题工具窗口中使用每个问题项的上下文菜单(如图 6-11 所示)。
图 6-11
在问题工具窗口中使用上下文菜单
如果你选择“显示快速修复”,IntelliJ 会在问题工具窗口中显示快速修复的选项(如图 6-12 所示);这样,您就不必返回到源文件来执行修复。这会节省你的时间。
图 6-12
显示“快速修复”选项
当快速修复有多个选项时,IntelliJ 会向您显示选项,以便您可以滚动并选择合适的选项。在图 6-13 中,IntelliJ 试图提供帮助,并展示了它的建议,以修复它认为是一个打字错误——在我的例子中,我真的打算将它拼写为“firstnumber”IntelliJ 的词典中没有此项;这就是为什么它被标记为打字错误。我打算忽略它。
图 6-13
快速修复选项
导航问题列表中项目的另一种方法是拆分问题工具窗口的窗格。点击工具窗口的分格 图标(如图 6-14 ),可以在工具窗口看到程序源代码。可以使用常用的快速修复(选项+回车或者 Alt +回车)来修复问题。
图 6-14
问题工具窗口的拆分窗格
IntelliJ 给了我们很多处理检查问题的方法。导航检查问题的另一种方法是将鼠标悬停在滚动条的条纹上(如图 6-15 所示)。
图 6-15
滚动条上的条纹
黄色条纹显示警告,红色条纹显示错误。当您将鼠标悬停在条纹上时,警告和错误会显示在弹出对话框中,检查会在标注气球中突出显示(这样您就可以很容易地发现它们)。
IntelliJ 不仅能让您轻松发现检查问题,还能让您轻松解决这些问题。从滚动条中,您还可以访问快速修复(如图 6-16 所示)。
图 6-16
从滚动条快速修复
最后,您可以使用检测小工具的上下箭头键导航检测问题,如图 6-17 所示。
图 6-17
检测小部件的上下箭头键
如果您不喜欢使用鼠标,您可以使用 F2 或 Shift + F2 键跳过检查问题。
检查整个项目
您已经知道如何处理单个源文件中的问题;我们只需点击每个源文件上的检查小部件——任务完成。但是项目通常有多个源文件。如果您的项目有 100 个源文件,这是否意味着您需要单击检查小部件 100 次才能看到整个项目的问题?当然不是。IntelliJ 有办法对整个项目进行检查。
要对整个项目进行检查,进入主菜单栏,然后分析 ➤ 检查代码。或者,使用动作快捷键( Shift + cmd + A 或 Shift + CTRL + A ),然后选择检查代码,如图 6-18 所示。
图 6-18
检查代码操作
无论哪种方式,都将进入指定检查范围对话框(如图 6-19 )。
图 6-19
指定检查范围
选择“整个项目”来运行整个项目的检查。然后 IntelliJ 对整个项目运行检查扫描,并弹出问题工具窗口来显示检查问题的完整列表。如果你有一个大项目,这可能需要一些时间。
图 6-20 显示了问题工具窗口,其中列出了检查发现的所有问题。
图 6-20
整个项目的检查清单
问题是按类别组织的,而不是按位置(源文件)组织的。正如您在我们的小示例项目中看到的,它按类别列出了问题,如数据流、声明冗余、可能的错误和校对。
现在,您可以浏览每个问题,并使用各种解决方法来解决它们。
在可能的情况下,IntelliJ 以一组布局良好的按钮提供解决方案,如图 6-21 所示。如果你想使用这个或者你更愿意使用可靠的选项+ ENTER 快捷键,这完全取决于你。
图 6-21
IntelliJ 提供了可能的解决方案。
意向行动
灯泡并不总是意味着你的代码有问题。IntelliJ 还使用黄色灯泡向您展示可以改进代码的地方。
让我们举一个简单的例子来说明如何使用意图动作。考虑图 6-22 中所示的以下代码。
图 6-22
打印时的意图
使用我们的快速修复快捷方式(option + ENTER 或 Alt + ENTER),IntelliJ 为我们提供了几种改进代码的方法。正如你在图 6-23 中看到的,我们可以选择用 StringBuilder.append()或 MessageFormat.format()替换字符串表达式,或者用格式化的 printf()替换 println 选择哪一个完全取决于你的喜好。我偏向于 printf()选项,但这只是我自己。
图 6-23
我们 println 示例的意图操作
不是所有的意图行为都是有用的(或正确的,取决于你的上下文)。事实上,其中一些是彻头彻尾的讨厌,就像图 6-24 中显示的这个。
图 6-24
分割申报意向行动
它建议我们这样做。
Random random;
random = new Random();
而不是这个;
Random random = new Random();
这个建议在这种情况下没有意义。内联声明和定义更有意义。
幸运的是,您可以为任何意图定制行为。所以,让我们现在解决那个讨厌的分裂声明意图。
使用快速修复快捷键(option + ENTER 或 Alt + ENTER),然后点击右箭头(如图 6-25 )。
图 6-25
编辑意向设置
从这里,您可以禁用“拆分声明”意图或编辑意图设置;任何一种选择都会使意图行动沉默。IntelliJ 不会再用它来烦你了。但是,出于某种原因,您希望恢复意图操作,您可以在 IDE 的首选项或设置中这样做。这是在编辑 ➤ 的意图下的。使用到处搜索键盘快捷键(双 Shift),然后输入“意图”(如图 6-26 )。
图 6-26
弹出意图对话框的快捷键
在随后的对话框中,在意向对话框中查找“拆分申报项”,如图 6-27 所示。您可以使用意向对话框中的搜索文本字段来快速缩小选项范围。
图 6-27
意向对话框中的拆分申报条目
如您所见,Split 声明被禁用了——因为我们不久前取消了它。当您在主编辑器或问题工具窗口中抑制一个意图时,该意图动作在首选项(或设置,如果您在 Linux/Windows 上)中被禁用。
使用偏好 ➤ 意图来定制 IntelliJ 在建议代码改进时的行为。如果你对某些意图感到恼火,就压制它们。
关键要点
-
注意编辑器的灯泡和曲线。当您看到它们时,意味着 IDE 发现了一些次优代码。
-
无论你在哪里看到灯泡或曲线,只要按下 option + ENTER(对于 Windows/Linux,按 Alt + ENTER)就可以快速修复。快速解决的捷径是你的朋友。
-
IntelliJ 并不总是正确的。有些建议对你来说可能没有意义。你可以在偏好设置(或设置) ➤ 编辑 ➤ 意图中关闭它们。
七、重构
在本章中,我们将介绍以下内容:
-
重构概述
-
常见的(也是重要的)重构操作
-
IntelliJ 如何重构
“技术债务”、“干燥原则”、“干净的代码”——在代码评审中听过这些术语吗?开发会议,也许?我打赌你有。这些可能是现在的流行语,但它们不是空的。这些术语被创造出来(并变得流行)是有充分理由的。
构建一个新应用最令人兴奋的部分(至少对我来说)是最初的编码阶段。这总是一个爆炸,但随着项目进入维护阶段——您最初的技术决策开始困扰您——它变得越来越不有趣。事实上,它开始感觉像一件苦差事。维护阶段不令人兴奋的一个常见原因是,当您在大量代码的基础上编写新功能时,添加新功能要困难得多。最微小的错误可以破坏很多东西,当你修复一件东西时,你会破坏两件东西。这就是为什么你真的应该养成对你的代码进行单元测试的习惯——但是我们在这里超越了自己;这不是本章的内容;我们很快就会处理测试的问题。无论如何,关键是,如果代码是干净的,易读的,并且有点条理,那么维护代码的工作就不那么可怕了。
重构基本上是重写和改进源代码——使它们易于阅读——而不改变其可观察到的行为。有组织的、整洁的、易读的代码比无组织的、混乱的、复杂的代码更好——这使得代码更容易维护和扩展。在这一章中,我们将讨论重构以及 IntelliJ 是如何让重构变得容易的。
重构
没有人会着手编写复杂、混乱和无组织的代码。代码复杂性不是任何程序员开始项目时的目标。代码开始很简单,如果你能相信的话;然后,随着我们添加更多的代码,复杂性越来越多——一个接一个。如果你不能控制复杂性,你很可能会以“意大利面条式的代码”而告终,这些代码真的很难解开。那么,我们如何管理这种情况呢?很多方法,其中之一是通过重构。
当你重构时,你只是以一种更有组织性的方式移动代码片段;但是它不会改变代码的行为。让我们考虑清单 7-1 中的代码;该方法只需调用一个例程来打印一些横幅数据,计算未清余额,打印发票,最后打印未清余额。
void printSomething(Invoice invoice) {
printBanner();
double outstanding = calculateOutstanding();
// print details
System.out.println(customer);
System.out.println(outstanding);
}
Listing 7-1printSomething() Method
在某些时候,我们可能需要打印客户发票和代码库中其他地方的未清余额。创建一个打印详细信息的方法,这样我们就不必编写前面示例代码的最后两个 println()语句,难道不是很有意义吗?清单 7-2 向我们展示了如何操作。
void printSomething(Invoice invoice) {
printBanner();
double outstanding = calculateOutstanding();
printDetails(invoice, outstanding);
}
private void printDetails(Invoice invoice, double outstanding) {
System.out.println(invoice);
System.out.println(outstanding);
}
Listing 7-2Refactored printSomething() Method
看到多简单了吧?我们只是移动了一些代码。现在,每当我们需要打印客户的详细信息时,我们只需调用 printDetails()。
我们刚刚做的重构叫做“提取方法”重构。这些重构行为有一个完整的目录——你可以在 https://refactoring.com/catalog/
找到。目录中列出了 60 多个重构操作。我怀疑你会需要全部 60 个。作为实验,你可以去 GitHub 搜索每个重构动作的名字。例如,搜索“重命名变量”(如图 7-1 )。
图 7-1
GitHub 上的“重命名变量”搜索
GitHub 上有超过 100 万次的“重命名变量”操作。当然,并不是所有的重构操作都记录在提交消息中,但是这是对现实世界重构活动的一个不错的近似。
用这些简陋的研究方法,下面是我在 GitHub 上的发现。在撰写本文时,“重命名变量”操作以超过 100 万次提交高居榜首。
以下列表显示了我的部分发现:
-
重命名变量–1M+
-
重命名方法–178k
-
重命名类别–143k
-
移动方法–109k
-
移动等级–97K
-
提取方法–95K
-
内嵌方法–81K
-
提取等级–23K
-
提取接口–18K
-
提取超类–2K
-
引入断言–2K
-
上拉方法–1K
-
引入参数对象- 674
-
下推方法–168
何时重构
你怎么知道什么时候应该重构?
肯特·贝克是“极限编程”的创始人,也是“敏捷宣言”的 17 个原始签名人之一,他推广了“代码气味”这个术语。在马丁·福勒的《重构:改进现有代码的设计》一书中,这个术语的使用增加了。
当一个代码需要重构时,它被称为有“味道”,不是字面上的意思——它只是意味着代码读起来没有吸引力或不愉快。以下是一些代码气味的例子:
-
大类–在现有的类中添加新的方法或行为通常更容易;这就是一个阶层成长的原因。随着时间的推移,太多的功能被塞进了这个类。您可能需要将它的一些功能重新定位到一个新类中。
-
长方法(Long method)——当你把很多功能塞进一个方法时,就会出现这种情况。节约切换和简单地将行为保持在现有方法内的冲动太强烈了,因此该方法不断发展。这里有一个小提示:当你觉得你必须写一个注释来解释下一行代码时,这通常是一个信号,你应该把下一行代码放到它自己的方法中。
-
大量原始类型被使用–当原始成员变量的数量随着时间增长时,可能是时候回顾一下你对问题域的抽象了。
-
参数过多–这通常与前面提到的“长方法”同时发生。参数太多,可能是因为这个方法做得太多了。它实现了太多的算法。或者是时候再次回顾你的抽象了。与其传递许多参数,不如传递一个对象。
有很多代码的味道;在这一章中,我们不可能把它们都讲清楚,因为我们应该讨论如何在 IntelliJ 中进行重构。
Note
随着您获得更多的经验,您手动检测“代码气味”的能力将会增强——在此之前,您可能希望使用一些工具来帮助您找到不良代码。SonarLink 是一个不错的起点。它是 IntelliJ 的一个插件。你可以从 www.sonarlink.org
网站获取 SonarLink。
IntelliJ 中的重构
现在我们已经对重构有了相当多的了解,是时候看看它的实际应用了。
要开始重构,您需要选择想要重构的代码片段(目标)。它可以是一个符号,也可以只是一段代码。您可以在编辑器或结构工具窗口中选择符号—我通常只在编辑器中选择代码;这样感觉更自然。通常在符号上有插入符号就足够了。IntelliJ 自动扩展选择,如图 7-2 所示,我在姓氏符号的某处放置了插入符号。
图 7-2
IntelliJ 自动扩展选择
如您所见,IntelliJ 已经突出显示了姓氏符号的用法,即使我还没有要求它做任何事情。IDE 会预测您的行动。
一旦选择了目标,现在就可以选择重构操作了。您可以通过几种方式做到这一点:
-
通过主菜单栏,选择重构,然后选择重构操作。
-
使用上下文菜单。右键单击该符号,然后选择重构,再选择重构操作。
-
使用键盘快捷键 CTRL + T (macOS)或者CTRL+Shift+Alt+T(Linux/Windows),然后选择重构动作。
继续我们的例子,让我们将变量的姓氏重命名为的名字。一旦我在姓氏符号上有了插入符号,我将使用键盘显示“重构这个”对话框(如图 7-3 所示)。顺便说一下,当你显示“重构这个”对话框时,显示了各种重构操作的键盘快捷键:Shift + F6 用于重命名,F6 用于移动成员,F5 用于复制类,等等。您可以选择记住这些单独的快捷方式(这是访问它们的最快方式),或者如果您有点懒(像我一样),我可以只使用右键单击或 CTRL+T——反正它会带我到“重构这个”对话框。
图 7-3
“重构此”对话框
让我们选择“重命名”;毕竟,我们想要重命名一个变量。选择“重命名”后,IntelliJ 会高亮显示正在编辑的符号,并立即相应地更改符号的出现,如图 7-4 所示。
图 7-4
重构变量
完成编辑后,按 ENTER 键。
如果您注意到了,在我们的示例代码中,变量 lastName 和 firstName 有 getters 和 setters。IntelliJ 还建议我们是否要改变 getters 和 setters(如图 7-5 所示)。
图 7-5
重命名 Getters 和 Setters
对话框的底部面板显示了代码更改的预览(图 7-5 )。单击确定完成操作。
清单 7-3 显示了重构后的 Person 类。
class Person {
private String lname;
private String firstName;
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
Listing 7-3Refactored Person class
你可能会认为这只是一个美化了的“搜索和替换”操作,任何一个像样的编辑器都可以做,但它不仅仅是这样。当您需要在更大范围内重命名一些东西时,比如一个类、包或者一个广泛使用的公共方法,重构操作的价值就变得显而易见了。在重命名操作期间,IntelliJ 执行以下操作:
-
它检查当前作用域中的名称冲突。
-
它验证新名称在语法上是合法的。
-
如果你重命名一个类或包,它会创建新的文件和目录,并删除旧的。
-
它会更新版本控制系统中由于名称更改而从源代码树中添加或删除的任何文件。
-
它会更正对您重命名的符号的所有直接代码引用,以确保它们使用新名称。
-
它甚至更新 JavaDoc 注释。
-
它更新任何受影响的导入语句。
IntelliJ 中的更多重构
我相信您已经掌握了它的窍门,我可能会让您自己去尝试如何做其他的重构操作——但是让我们再做几个,好吗?
提取方法
当你“闻到”代码越来越长时,你可能想要使用“提取方法”重构操作。您将提取方法,因为您想要抽象操作并将一些行为封装在一个单独的方法中;这样,就可以从代码的其他部分重用它。
图 7-6 显示了 printSomething()方法——你之前已经看过这段代码了。我在本章前面用这个作为例子。您已经知道这将如何被重构。
图 7-6
printSomething()方法
我们希望提取第 13 行和第 14 行,并将它们放在一个单独的方法中。为此,我将突出显示第 13 行和第 14 行(如图 7-7 所示),然后弹出“Refactor This”对话框。
图 7-7
提取方法
选择“提取方法”操作;一旦我选择了动作,IntelliJ 就会显示一个变化的实时预览。提取的方法——恰当地命名为“extracted()”——在后台显示并点亮(如图 7-8 所示)。
图 7-8
提取的()方法显示在预览中
此时,IntelliJ 还没有完成重构操作。如您所见,选择“extracted()”方法签名是因为 IntelliJ 正在等我键入新方法的名称。因此,我将输入新提取的方法的名称。我将名称改为“printDetails()”,如图 7-9 所示。
图 7-9
print 细节()方法
像以前一样,IntelliJ 会在您键入时显示更改的实时预览。
当您对方法名的更改感到满意时,按 ENTER 键完成重构操作。重构之后,您可能需要做一些清理工作——不多,但有时可能需要做一些小的修改。
移动成员
您可以将成员变量或方法从一个类移动到另一个类,但是请注意,您只能移动静态成员——IntelliJ 不允许您移动实例成员。
要移动一个类成员,将插入符号定位在你想要移动的符号上,然后弹出“重构”对话框,如图 7-10 所示。
图 7-10
移动成员
选择“移动成员”在接下来的屏幕中(图 7-11 ,您可以选择目的地。您需要告诉 IntelliJ 您想要将成员移动到哪里。
图 7-11
移动静态成员
单击省略号按钮(在“完全限定名称”字段的右侧)。您可以在随后的对话框中选择目标类别(如图 7-12 所示)。
图 7-12
选择目的地类别
点击 OK 以完成选择,之后您将返回到上一个对话框,但是这一次,destination 字段包含目标类的全限定名称(如图 7-13 所示)。
图 7-13
移动静态成员(填满)
点击重构完成动作。
更改签名
如果您需要更改方法的签名,在手动更改之前请三思。IntelliJ 真的可以在处理变更的后果方面为您节省大量时间。如果您手动执行,您可能无法获得该方法的所有引用 IDE 不会错过任何一个节拍。
让我们更改我们前面的示例“printDetails()”方法的签名。将插入符号放在方法名上,弹出“重构”对话框,如图 7-14 所示。
图 7-14
更改 printDetails()的签名
选择“更改签名”操作。弹出更改签名对话框(如图 7-15 )。
图 7-15
更改签名对话框
在此对话框中,您可以更改成员的可见性、返回类型、名称,甚至参数的顺序。
图 7-16 显示了我所做的一些更改的更改签名对话框。
图 7-16
更改签名(包含我的更改)
如您所见,我将方法的名称更改为“printSomeDetails()”,将返回类型更改为 int,还将其可见性更改为“protected”。
对话框的底部面板显示了方法签名的预览(包含您的更改)。此时,如果您已经对您的更改感到满意,您可以单击“重构”来完成操作。或者,您可以单击“预览”按钮,在提交操作之前查看重构预览。重构预览如图 7-17 所示。
图 7-17
重构预览
您可以在预览中检查建议的重构的细节。当您对更改满意时,单击“Do Refactor”按钮完成操作。否则,单击“取消”按钮中止操作。
关键要点
-
重构不仅为其他人,也为我们自己保持我们代码库的健全。三个月后,你将不会记得在写那段漂亮的代码时的想法。
-
IntelliJ 的重构工具比“查找和替换”要好得多。在手动操作之前,尽可能尝试使用重构工具。
-
如果你只能记住一个重构的快捷方式,那就让它成为 CTRL + T (对于 macOS 用户)或者 CTRL + Shift + Alt + T (对于 PC 用户)。
八、实时模板
在本章中,我们将介绍以下内容:
-
实时模板
-
使用实时模板
-
创建您自己的实时模板
出于各种原因,Java 与开发人员之间有一种又爱又恨的关系。如果我是一个打赌的人,我会说 Java 被讨厌的原因之一是因为冗长。要完成任何事情,你必须忍受它的锅炉板代码。您有几个选择:
-
转到 Python——你需要转行,可能会离开现在的工作(剧烈的)。
-
切换到科特林——有可能。许多 Java 商店现在都在采用 Kotlin。你也许根本不需要跳槽,但你真的想跳槽吗?Java 是你的初恋吧?
-
咬紧牙关,奋力前进,输入密码–哎哟!你好,腕管综合症。
-
使用 IntelliJ 的实时模板–耶!你的手指(和键盘)会为此感谢你的。这就是本章的全部内容。
那么什么是活模板呢?
你以前使用过文本扩展器吗——你输入一些字母模式,比如 datetoday 它会扩展到当前日期或者 tgif ,它会扩展到“谢天谢地今天是星期五”?实时模板与此非常相似。这是 IntelliJ 的一个特性,你可以输入一个助记符(或类似的东西),它可以扩展为一个表达式或结构。
你想看看实际情况吗?下次定义一个类并且需要编写 main()方法时,键入单词“main”(如图 8-1 所示),然后按 ENTER 或 TAB 展开模板。
图 8-1
使用“main”live 模板插入公共静态 void main
当模板展开时,您将拥有一个空的 main()方法(如图 8-2 所示)。IDE 还会将插入符号放在方法的第一个空行上。想得很周到。这样,您就可以开始在方法中键入第一行,而无需重新定位光标。
图 8-2
扩展了“主”实时模板
main 方法还有另一个模板。尝试输入“psvm”,如图 8-3 所示。
图 8-3
使用“psvm”模板
按 ENTER 或 TAB 也将“psvm”扩展为public static void main()
方法。现在,在到达 main 的第一个空行后,尝试输入“so”,如图 8-4 所示。
图 8-4
IntelliJ 展示了一些以“so”开头的实时模板
我们想写 System.out.println(),所以选择“sout”选择“sout”时按 ENTER 或 TAB 键,将模板展开到system . out . println();如图 8-5 所示。
图 8-5
“sout”扩展为 system . out . println();
到目前为止,您已经输入了八个键(“main”和“So”,包括选项卡),它扩展到了 58 个字符。这就意味着你再也不用输入 50 个字符了——非常简洁,对吧?想象一下,如果你真的可以使用 Java 的所有 38 个实时模板。击键的节省是巨大的。
参数化模板
我们再举一个例子;在主方法中,输入“for”,如图 8-6 所示。
图 8-6
使用“fori”模板
可以看到,IntelliJ 为我们呈现了三个选项:(1),扩展为 for 循环结构;(2) fori ,扩展成更全面的 for 循环结构;以及(3) foreach ,这是您在处理集合时可能会用到的。让我们用“fori”;选择“fori”时,按 TAB 或 ENTER 键。IntelliJ 将其扩展为近乎完整的 for 循环结构(如图 8-7 )。
**
图 8-7
“fori”扩展了
它有一个起始计数器值、极限表达式和计数器增量表达式。随着模板的扩展,脱字符号落在 " i "上,以防您想要更改计数器变量(我通常不去管它)。如果您再次按 TAB,插入符号会停留在您应该键入限制表达式的值的地方(如图 8-8 所示)。
图 8-8
按 TAB 键会将您带到限制表达式
请注意,每次按 TAB 都会将插入符号定位到一个占位符上,您应该在这里输入值以完成语句。
再按一次 TAB,它应该将脱字符号放在“for”语句的第一个空行上(如图 8-9 所示)。
图 8-9
最后一次按 TAB 键
你应该已经找到窍门了。使用实时模板非常容易。你应该随时随地使用它们。他们节省时间。
显示所有可用模板
实时模板知道它们的上下文。你不能在任何地方使用它们。例如,尝试在方法之外键入“fori”(如图 8-10 所示)。
图 8-10
在方法外部键入“fori”
看看 IntelliJ 是如何将其标记为错误的?“fori”模板在方法之外没有意义。模板知道上下文。他们知道他们应该在哪里。
IntelliJ 总是尽力提供帮助。当您在编辑器中键入一串字符时,很难预测您要做什么。在图 8-11 中,当我键入“p”时,它试图建议一堆选项,很难区分哪些是实时模板,哪些不是。根据经验,如果它(1)没有括号或花括号,并且(2)没有有用的描述,那么它就不是一个活模板。
图 8-11
显示以“p”开头的可能模板
你能在图 8-11 中找出哪些是实时模板吗?
如果你猜对了 prsf、psf 和 psfi,那你就猜对了。
如果你想显示所有实时模板的列表(插入符号所在),只需使用 cmd + J (macOS)或 CTRL + J (Windows 和 Linux)并滚动即可。图 8-12 显示了所有实时模板的下拉列表。
图 8-12
实时模板列表
环绕实时模板
考虑清单 8-1 中的代码;这是一组典型的 Java 类,演示了如何实现单例——它不是一个合适的单例,所以不要在生产中使用它,但它足以演示如何控制对象实例数量的基本流程。
public class MainProgram {
public static void main(String[] args) {
Tree objTree = null;
objTree = TreeFactory.getTree();
}
}
class TreeFactory {
private static Tree tree;
private TreeFactory() {
tree = new Tree();
}
public static Tree getTree() throws Exception {
return tree;
}
}
class Tree { }
Listing 8-1TreeFactory, Tree, and MainProgram Classes
假设我们想用 try-catch 包围 getTree()调用;您可以使用实时模板来节省一些击键。
要用任何控制流结构包围一个语句,将插入符号放在您想要包围的行上,然后使用键盘快捷键 cmd + option + T (macOS)或 CTRL + Alt + T (Linux 和 Windows)。
弹出包围对话框,选择要使用的控制结构,如图 8-13 所示。
图 8-13
使用“包围”模板
选择 try-catch,然后按 ENTER 键。
图 8-14 显示了活动模板完成的动作。
图 8-14
扩展的试玩直播模板
如您所见,try-catch 模板用适当的 catch 表达式甚至 printStackTrace()语句预先填充了控制结构。
让我们进一步举个例子。现在,将插入符号放在 try-catch 结构的外部。我们将检查对 getTree()的调用是否返回 null。图 8-15 向我们展示了如何使用实时模板来完成这项工作。
图 8-15
使用 if null (ifn)模板
键入“if”并等待实时模板显示选项。
选择“ifn”并按回车键。
图 8-16 显示实时模板知道哪些变量在范围内。
图 8-16
显示哪些变量在范围内的实时模板
当然,我们想要测试的是 objTree 变量,所以选择它。清单 8-2 显示了我们完成的主程序。
public class MainProgram {
public static void main(String[] args) {
Tree objTree = null;
try {
objTree = TreeFactory.getTree();
} catch (Exception e) {
e.printStackTrace();
}
if (objTree == null) {
}
}
}
Listing 8-2MainProgram
一旦你掌握了其中的诀窍,你会想知道没有这些你是如何编码的。它们真的会节省你无数的打字时间。
创建您自己的模板
您可以在 IDE 的首选项或设置中多了解一些实时模板。要得到它,在 macOS 上使用 cmd +,在 Windows/Linux 上使用(逗号)或CTRL+Alt+S;然后进入编辑器 ➤ 直播模板。
您会看到模板是按语言分组的(如图 8-17 所示)。
图 8-17
首选项对话框中的实时模板
单击“Java 语言”展开选择;这显示了所有 38 个 Java 实时模板(如图 8-18 所示)。
图 8-18
Java Live 模板
当您单击每个项目时,IntelliJ 会显示每个实时模板的详细信息。您可以看到模板文本和几个影响模板行为的其他选项,如图 8-19 所示。
图 8-19
模板文本
为了深入挖掘实时模板,我们为什么不创建一个自己的模板。我们可以创建一个实时模板,并将其添加到现有的模板组中,但我不想弄乱现有的一组实时模板。因此,让我们创建一个新的模板组。
点击实时模板对话框上的加号(如图 8-20 所示)并点击“模板组”
图 8-20
添加模板组
在随后的屏幕中,输入模板组的名称;我将称之为“我的模板”,如图 8-21 所示。
图 8-21
创建新组
选中“mytemplates”组时,再次单击加号;这次,点击“实时模板”,如图 8-22 所示。
图 8-22
新建实时模板
在接下来的屏幕中,您可以填写模板详细信息,如图 8-23 所示。
图 8-23
新模板详细信息
-
缩写–这将是实时模板的快捷键。这不能与任何现有的实时模板相同。此外,花时间想清楚这一点;它也需要容易记忆。至于我们的例子,我将使用 publicmethod。
-
描述–这是您将在实时模板右侧看到的描述,如下拉列表所示。
-
模板文本–这是模板展开时的正文。模板文本中的变量(被美元符号包围的那些)是程序员在模板扩展时必须填充的变量。在我们的例子中,我使用了四个变量——您可以使用更多(或更少)。模板文本中的所有变量都是任意的,这意味着我只是编造了它们,除了 \(END\) 变量;那是一个预定义的模板变量,对 IntelliJ 有特殊的意义。\(END\)变量指示代码完成时插入符号或光标的结束位置。您不能再使用 TAB 键导航到下一站。
我想再次参考图 8-23 。注意到左下方写着“没有适用的上下文”吗?这意味着我们必须告诉 IntelliJ 我们的新模板可以从哪个上下文中调用——我们是否可以在方法之外、方法之内调用它,等等。
要为我们的新模板定义上下文,请单击“定义”链接,如图 8-24 所示。然后选择“声明”
图 8-24
模板上下文
当我们选择“声明”时,意味着我们可以在任何需要声明的地方使用我们的模板。
现在,对其进行测试(参见图 8-25 )。
图 8-25
我们正在使用的新模板
选择“publicmethod”,然后按 ENTER 键。图 8-26 显示了扩展的模板——它工作了!
图 8-26
扩展的 publicmethod 模板
共享模板
如果你用的是其他 JetBrains 的 IDE (WebStorm,Rider,PyCharm 等。),将您的 IntelliJ 模板导出到那些其他 ide——或者其他也使用 IntelliJ 的人。
您可以通过导出 live 模板来共享它们;为此,您需要
图 8-27
导出设置
-
进入主菜单栏,然后文件 ➤ 管理 IDE 设置 ➤ 导出设置。
-
在“导出设置”对话框(如图 8-27 所示)中,确保选择了 Live Templates 框,并指定保存导出设置的档案的路径和名称。
-
单击确定完成导出操作。
要导入模板,请执行以下操作:
-
在主菜单栏上,进入文件 ➤ 管理 IDE 设置 ➤ 导入设置。
-
使用导出的模板配置指定归档文件的路径。
-
在导入设置对话框中,选择实时模板复选框,然后点击确定按钮完成导入操作。
-
重新启动 IntelliJ(或另一个 JetBrains IDE)。你应该在 IDE 设置的编辑器 ➤ 实时模板页面上看到导入的实时模板。
关键要点
-
Java 是一种相当冗长的语言。如果不使用文本扩展工具,可能会严重伤害手指。谢天谢地,IntelliJ 有实时模板。如果你想知道你节省了多少击键次数,只要去 IntelliJ 的主菜单栏,然后去帮助➤生产力指南。它会显示您的使用统计数据。
-
IntelliJ 有 38 个模板(仅针对 Java 学好它们是值得的。你的手指(和键盘)会为此感谢你的。
-
你不局限于预定义的模板;您可以添加自己的模板。如你所见,这很容易做到。**
九、故障排除
在本章中,我们将介绍以下内容:
-
您最有可能遇到的错误
-
记录调试语句
-
使用调试器
大多数(如果不是全部的话)程序都会有错误——我这里说的是不平凡的程序,不是“Hello World”那种。作为一名开发人员,处理错误将是你职业的一大部分。在这一章中,我们将讨论你最有可能遇到的错误,以及如何使用 IntelliJ 来处理这些错误。
错误类型
通常,您会遇到以下几种错误:
-
句法误差
-
运行时错误
-
逻辑错误
句法误差
语法错误就是你所认为的语法错误。发生这种情况是因为你在代码中写了一些 Java 编译器的规则集不允许的东西。编译器不理解它。错误可能很简单,比如忘记关闭括号或缺少一对花括号。它也可能很复杂,比如在使用泛型时,将错误类型的参数传递给函数或参数化类。
每当您在主编辑器上看到红色的曲线时,您可以轻松地用 IntelliJ 捕捉语法错误,如图 9-1 所示。
图 9-1
主编辑器显示一个语法错误指示器
当你看到这样一条弯弯曲曲的红线时,这意味着你有一个语法错误。IntelliJ 将红色曲线放在非常靠近违规代码的地方。如果您将鼠标悬停在红色曲线上,大多数情况下,IDE 可以非常准确地告诉您代码有什么问题,这样您就可以轻松地找到并修复这些代码。
除了语法错误之外,当您试图编译使用不同的 JDK(旧版本或完全不同的 JDK)构建的代码时,您还可能会遇到编译错误。
运行时错误
运行时错误发生在你的代码遇到了意想不到的情况时。顾名思义,这个错误只在程序运行时发生。这不是你在编译时会看到的。
Java 有两种类型的异常,选中的和未选中的。IntelliJ 在检查异常方面给了你很多帮助。图 9-2 显示了当你试图调用一个抛出检查异常的方法时,在主编辑器中会发生什么。
图 9-2
显示未处理异常信息的主编辑器
IntelliJ 试图通过标记未处理的异常来提供帮助,如图 9-2 所示。如果您将鼠标悬停在弯曲的红线上足够长的时间,IntelliJ 会显示代码被标记的原因,甚至会给出如何修复它的建议。
关于检查的和未检查的异常:检查的异常是 Java 编译器在编译期间检查(或检查)的东西。如果一个方法声明它抛出一个检查过的异常(例如,FileNotFoundException、ClassNotFoundException、IOException、SQLException 等)。),则该方法必须通过将调用包含在 try-catch 中或通过重新引发异常来处理异常。
另一方面,未检查的异常在编译时不会被检查,这意味着您不需要为 try-catches 费心;你可以像任何坏事都不会发生在你的应用上一样编码。在像 C++和 Kotlin 这样的语言中,所有的异常都是未检查的,所以您可以省去 try-catch 块——如果您愿意,您仍然可以处理异常,但这是可选的。
标记和提示未处理异常的解决方案已经很好了,但是 IntelliJ 还提供了快速修复。快速修复是 IntelliJ 对它在设计时检测到的错误的修复操作;这很容易执行——你只需要在突出显示的代码问题上按下 Alt + ENTER (对于 Linux 和 Windows 用户)或 cmd + ENTER (如果你在 macOS 上),然后选择一个适当的操作过程。图 9-3 显示了这一点。
图 9-3
快速修复我们未处理的异常
清单 9-1 显示了发送者类(带有自动修正的代码)。
class Sender extends Thread {
public void run() {
try {
inputStream = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Listing 9-1Class Sender
IntelliJ 尽职尽责地将适当的 try-catch 结构添加到代码中——它甚至正确地格式化了代码。不过,它没有添加 finally 子句,您必须自己编写。
逻辑错误
逻辑错误是最难发现的。顾名思义,这是你逻辑上的错误。当你的代码没有做你认为它应该做的事情时,那就是逻辑错误。有许多方法可以应对它,但最受欢迎的是使用 System.out.println() 或 Logger 类(来自 java.util.logging)。
当你检查你的代码时,你会发现某些领域你对正在发生的事情非常确定,但是也有一些领域你不太确定;在这些领域,println 或 Logger 最有用。就像留下面包屑让你跟着。
调试器
IntelliJ 是一个全功能的 IDE。它带有一个强大的调试器。虽然您可以使用 println 和 Logger 语句在您的代码中使用 sleuth,但是当您在使用 code-detective 时,使用调试器会得到更好的结果——它也更容易使用,因为它不会使您的代码混乱。
让我们考虑下面的代码(如清单 9-2 所示)来演示 IDEA 调试器。
package net.workingdev.ideabook;
import java.util.ArrayList;
import java.util.List;
public class DebugSample {
public static void main(String[] args) {
List sampleNames = createNames();
printNames(sampleNames);
addName(sampleNames, "Jane Doe");
printNames(sampleNames);
}
private static List createNames() {
ArrayList listNames = new ArrayList<String>();
listNames.add("John Doe");
listNames.add("Jane Doe");
return listNames;
}
private static void printNames(List<String> names) {
for (String name : names) {
System.out.println(name);
}
}
private static void addName(List<String> l, String name) {
l.add(name);
}
private static void removeNames(List l, String name) {
int position = l.indexOf(name);
if (position == -1) {
// the name is not in the list
}
else {
l.remove(position);
printNames(l);
}
}
}
Listing 9-2DebugSample Class
代码有五个方法(包括 main)。方法 createNames() 创建一个名字列表并返回它。方法 printNames() 接受一个姓名列表,并打印列表中的每一项。 addName() 方法接受一个列表和一个字符串;然后,它将字符串(第二个参数)添加到列表中。最后, removeName() 方法接受一个列表和一个字符串;它在列表中搜索第二个参数的出现;如果找到了,就删除该字符串,并再次打印列表。
您可以通过多种方式启动调试器:
图 9-5
从主方法的上下文菜单中运行调试
图 9-4
从底层调试
-
你可以点击装订线区域的运行图标(如图 9-4 所示),然后选择“调试”
-
可以使用类的 main 方法的上下文菜单,然后选择“调试”(如图 9-5 )。您可以通过左键单击 main 方法或使用 main 方法上的快速修复键来完成此操作——在 Windows/Linux 上,快速修复键是 Alt + ENTER ,在 macOS 上是 cmd + ENTER 。
-
或者,您可以从 IntelliJ 的主菜单栏启动调试器;转到运行➤调试。
现在,我们的代码愉快地浏览着它的逻辑;它创建一个名称列表,打印名称,添加名称,然后再次打印名称——您可以在 IntelliJ 的输出窗口中看到这一点(图 9-6 )。
图 9-6
示例代码的调试会话
可以说,当您想要查看(执行)情况时,调试器变得非常有用,我们可以通过几种方式来做到这一点。我们可以在代码中的指定位置暂停、恢复、重启或停止调试器。
当你的应用程序看起来没有反应时——这意味着它卡在了某个地方——你可以使用调试器来分析代码卡在了哪里。目前,我们的示例代码小而简单;这就是为什么它从头到尾都很轻松。让我们修改一下我们的 main 方法,让它模拟一个“卡住”的代码。清单 9-3 显示了修改后的 main 方法。
public static void main (String[] args) throws IOException {
List sampleNames = createNames();
printNames(sampleNames);
addName(sampleNames, "Jane Doe");
System.in.read();
printNames(sampleNames);
}
Listing 9-3Modified Main Method
对System.in.read()
的调用将停止程序执行;它在继续下一行之前等待用户输入。这对我们的目的来说足够好了。它模拟一个卡住的程序。现在,在调试模式下运行代码。
请注意,在输出窗口中,我们的流程没有完成(如图 9-7 所示)。卡住了。
图 9-7
DebugSample 在执行时停滞
现在点击调试器上的暂停按钮,如图 9-8 所示。
图 9-8
调试器的暂停按钮
一旦你暂停调试器,编辑器将向你显示它当前正在运行的类和方法——或者停留在那里(如图 9-9 所示)。在我们的例子中,它卡在了 System.in.read() 上;这就是为什么编辑器向我们展示了 FileInputStream 类的 readBytes() 方法——如果你切换到 Debug 窗口的调试器选项卡,你甚至可以看到堆栈跟踪(如图 9-10 所示)。
图 9-10
查看“调试器”选项卡上的堆栈跟踪
图 9-9
显示当前正在运行的调试器
现在,调试会话正在等待用户输入。按任意键,以便 System.in.read() 可以从标准输入中读取一些内容——这应该满足语句。
要继续调试会话,您可以按下恢复按钮(就在暂停按钮的正上方)。您需要的其他调试器按钮如下:
-
重启按钮–这将重启调试会话。你可以在扳手按钮的正上方找到这个按钮。
-
停止按钮–这将停止调试会话(在暂停按钮的正下方)。
分步操作
当调试会话暂停时,您可以使用调试器的各种步骤操作来“逐句通过您的代码”——步骤按钮如图 9-11 所示。
图 9-11
分步操作
-
步入(F7)——如果你想遍历每一行代码,使用这个。请记住,这将引导您遍历当前运行的类中当前运行的方法的每一行。如果该方法创建另一个对象并调用另一个方法,您将进入该另一个方法。
-
跳过(F8)——这允许你运行一行代码,然后继续下一行。
-
Force Step Into–这允许您调试 API 或库中定义的方法。如果 API 或库的源代码不可用,IntelliJ IDEA 会为您进行反编译和调试。
-
单步执行–这让您可以跳过逐行执行代码,返回到调用方法。被调用的方法会执行,但不会单步执行每一行代码。
-
Drop Frame–这允许您通过删除方法调用在代码执行过程中向后移动。
断点
断点是在代码中引入停止点的好方法。还记得在前面的调试示例会话中,我引入了 System.in.read() 来暂停代码吗?我们并不真的必须这样做;我们可以使用断点在特定的点暂停程序的执行。
要在一行代码上设置断点,请单击装订线区域(如图 9-12 所示)。
图 9-12
断点设置在第 12 行
我在第 12 行设置了断点。当您看到行号旁边的空白处有一个红点时,您就知道断点设置好了。
当您启动调试会话时,调试器将自动在断点处停止执行(如图 9-13 ),您无需再按暂停。
图 9-13
程序在断点处暂停
从这里开始,您可以使用我们之前讨论过的各种步进工具。
关键要点
-
您可能遇到的三种错误是编译类型或语法错误、运行时错误和逻辑错误。
-
语法错误是最容易修复的。IntelliJ 本身为您竭尽全力,因此您可以快速发现语法错误。有各种方法可以修复语法错误,但是大多数时候,快速修复应该可以做到。
-
通过设置断点和使用各种单步执行操作,可以一行一行地遍历代码。
十、源代码管理
在本章中,我们将介绍以下内容:
-
Git 简介
-
Git 中的基本操作
-
如何设置本地 Git repo
-
在 GitHub 上发布您的项目
当您与其他开发人员一起工作时,您需要一种方式来与其他人共享您的代码,并共享他们的代码作为回报。即使你是一个人工作,你也需要一种方法来跟踪你对代码库所做的改变。这些是您需要使用源代码控制的主要原因。
IntelliJ 可以与各种源代码控制系统一起工作,例如 Git、CVS、SVN、Mercurial 和 TFS。Git 是一个广泛使用的版本控制系统,这也是我们将在本章讨论的内容。
饭桶
Git 是一个免费的开源版本控制系统,最初由 Linus Torvalds 在 2005 年创建——Linus 负责 Linux 操作系统。Git 是一个分布式系统,不像 CVS 和 SVN 是集中式的。有了 Git,每个开发人员在本地都有他们代码 repo(repository 的缩写)的完整历史——repo 就是你所说的在版本控制下的文件夹。
Git 的分布式特性使得 repo 的初始克隆(复制)操作很慢——因为所有内容都被复制了——但后续操作(如提交、合并、比较和记录)要快得多。
我们不会深入 Git,但它通常是这样工作的:
-
您将创建一个项目文件夹,然后放置您的初始项目工件,例如,一个自述文件、几个源文件等。
-
初始化 Git 的文件夹。
-
将文件夹中的文件添加到源代码管理中;此时,您已经在源代码管理中进行了第一次更改——添加了一些文件。
-
提交您的更改。
-
在某个时候,您将编辑项目中的一些文件,甚至可能添加一些新文件。
-
将新文件添加到 Git,然后再次提交更改。
使用 Git 可以做更多的操作,比如分支、合并、责备、隐藏、拉取、克隆等等。,但我们现在保持简单。
在 IntelliJ 中使用 Git 之前,您需要先安装它。为了确定你是否已经有了 Git,获取一个终端窗口(或者 Windows 中的 cmd)并运行 Git 命令,如图 10-1 所示。
如果您不带任何参数或选项运行 Git 命令,它将打印一些使用信息,如图 10-1 所示。
图 10-1
饭桶
要找出您拥有的 Git 版本,您可以在运行 Git 命令时传递 version 参数,如图 10-2 所示。
图 10-2
Git 版本
如果您在运行 Git 后没有看到使用信息,而是看到类似“命令未找到”或“错误的命令或文件名”的消息,这意味着 Git 还没有安装。您需要先安装它,然后才能与 IntelliJ 一起使用。
可以从 https://git-scm.com
获得 Git 您会找到适合您平台的版本。git-SCM 网站上也有关于如何安装 git 的非常好的文档和说明,所以我们在这里不做介绍。
图 10-3 显示了撰写本文时 git-scm.com的网站。下载安装程序的链接位于页面的右下方。
图 10-3
git-scm.com 网站
将 Git 创建为本地存储库
安装 Git 后,您可以开始使用它来管理您的项目。
第一步是检查是否在 IntelliJ 中安装并启用了 Git 插件。如果您在 IntelliJ 的安装过程中接受了所有的默认设置,那么 Git、GitHub 和一些其他插件将会默认安装。无论如何,检查插件是否安装很容易——如果没有,只需在首选项(或设置)对话框中安装它。你可以通过 cmd +、 (macOS)或者CTRL+Alt+S(Linux/Windows)进入偏好设置对话框。
在首选项 ➤ 插件对话框中可以看到版本控制插件(如图 10-4 )。
图 10-4
Git 插件
打开要进行版本控制的项目;然后进入主菜单栏点击 VCS ,如图 10-5 所示。
图 10-5
启用版本控制
点击启用版本控制集成。IntelliJ 将要求您选择您想要使用的版本控制系统。图 10-6 显示弹出的对话框,您可以在其中选择版本控制系统。选择 Git。
图 10-6
启用版本控制集成
当您启用 Git 时,您会注意到 IDE 中的一些变化。首先,IntelliJ 会询问您是否想要将项目配置文件添加到 Git。对于您是否应该将项目配置文件添加到源代码控制中,并没有硬性规定,但是一般来说,我会建议您添加它们。JetBrains 对我们为什么要这么做有一个很好的解释。他们在 IntelliJ IDEA ( www.jetbrains.com/help/idea/2017.1/about-projects.html
)的在线帮助页面中进行了阐述。在谈到基于目录的格式时,JetBrains 说
-
那个。idea 目录包含一组配置文件(。xml)。每个文件仅包含属于某个功能区域的配置数据的一部分,这反映在文件名中,例如 compiler.xml、encodings.xml、modules.xml
-
几乎所有的文件都包含项目本身的核心信息,如组件模块的名称和位置、编译器设置等。因此,这些文件可以(也应该)在版本控制下保存。
如果您不使用 Gradle 或 Maven 之类的工具来管理依赖项,那么将项目配置文件置于源代码控制之下是一件好事。这样,每个人都可以获得项目及其依赖项的正确配置。但这也意味着每个人都必须按照您在配置文件中定义的方式来设置他们的环境。
另一方面,如果您将使用 Maven 或 Gradle 来管理依赖项,那么不要将项目配置文件添加到源代码控制中。配置文件中包含的所有信息都应该存储在 Maven/Gradle 文件中。然后,让每个人根据他们的环境配置他们的 IDE。
所以,现在,点击“总是添加”——你可以通过添加整个来覆盖这个设置。Git 忽略文件中的 idea 文件夹;我们稍后会谈到这一点。
图 10-7 显示 IntelliJ 提示我们将项目配置文件包含到源代码控制中。
图 10-7
添加项目配置文件
你可能注意到的 IDE 的另一个变化是在左下方的工具条中增加了一个新的部分(如图 10-8 所示)。
图 10-8
新的 Git 部分,添加到工具栏
工具栏上添加了一个 Git 按钮。
此时,我们已经将项目置于版本控制之下。我们已经创建了一个本地存储库(简称 repo ),用于存储我们的项目。
本地回购是一个受版本控制的文件夹,但它还没有任何上游回购——上游回购只是远程回购的另一个术语(就像 GitHub 或 Bitbucket 上托管的那些)。我们稍后会谈到这一点。
您还会注意到我们的 src 文件夹下的文件名(在项目工具窗口中)变成了红色。红色的文件名意味着它们还没有被添加到 Git 中。它们还没有升级。 iml 文件是绿色的,因为我之前添加了项目配置文件到 Git(当我点击提示添加配置文件到 Git 时,如图 10-7 )。
图 10-9 用红色显示主程序文件名。
图 10-9
主程序以红色亮起
有一些视觉上的暗示表明项目现在处于源代码控制之下,但是要真正确定这一点,我们可以看看项目的目录结构。您不会在项目结构中看到任何可见的变化,因为 Git 文件夹是隐藏的。要查看 Git 文件,你需要进入终端——在 macOS 中使用选项+ F12 快捷键,或者在 IntelliJ 中使用 Alt + F12 (对于 PC)弹出终端窗口。或者,只需单击 IDE 左下角工具栏上的“终端”按钮。
当终端打开时,您将自动位于项目的根文件夹中。发出一个 cd 命令去。git (点 git),然后发出命令列出目录的内容(如图 10-10 )。
图 10-10
的内容。git 文件夹
如你所见,里面有一堆文件和文件夹。
添加和提交更改
到目前为止,我添加到 Git 的唯一文件是我的项目配置文件。我还没有添加任何程序文件。我们可以通过几种方式做到这一点:
图 10-11
新建 Git 菜单项
-
我们可以进入主菜单栏,选择Git——这是一个新的菜单项。这发生在我们启用 Git 的时候(见图 10-11 )。
-
我们可以右击MainProgram.java(在项目工具窗口中),然后选择 Git ➤ 提交文件。
-
使用键盘快捷键“提交文件”,这是最快的方式。你应该试着“记住”这一点(双关语)。
在接下来的屏幕中,您将看到提交工具窗口(如图 10-12 所示)。
图 10-12
提交工具窗口
文件MainProgram.java仍然没有版本;要将其包含在变更列表中,点击文件名右边的勾选框(如图 10-13 )。
图 10-13
将文件提交给 Git
在提交工具窗口中,您将有机会包含或排除您希望包含在更改列表中的文件。勾选复选框,将该文件包括在提交中;勾掉,就不算了。就这么简单。
我添加了一行注释——“添加了主程序”——作为提交消息,然后单击提交按钮。现在,我的所有文件都已版本化,所有更改都已提交到本地存储库中。每当您在项目中添加和/或更改某些内容时,您都需要这样做。
分支
新创建的 Git repo 将有一个名为“master”的分支。要查看您的回购分支,请进入主菜单栏,然后选择 Git ➤ Branches 。分支对话框如图 10-14 所示。
图 10-14
Git 分支
您还可以使用 Git 分支对话框来创建项目的新分支。要为你的项目创建一个新的分支,只需点击对话框中的“+ New Branch”链接。在随后的屏幕中键入新分支的名称(如图 10-15 所示),然后单击“创建”
图 10-15
创建新分支
默认情况下,“签出分支”设置是打开的;大部分时间你都想戴着它。这意味着在创建分支后,您可以签出该分支。无论您做什么编辑或更改,它都将在新签出的分支上。
更改列表中的更改
当你在一个有很多文件的项目上工作时,知道哪些文件在最后一次提交后被改变了是很有用的;提交工具窗口(如图 10-16 所示)显示自上次提交以来所有被更改的文件。您可以通过点按工具栏上的标签来隐藏或取消隐藏它。或者,你也可以在主菜单栏中显示或隐藏它,查看 ➤ 工具窗口 ➤ 提交 —最快的方法是只使用 cmd + 0 (macOS)或 Alt + 0 (Linux/Windows)。
图 10-16
提交工具窗口
如果您想查看自上次提交以来文件发生了什么变化,只需在提交窗口中选择该文件(如图 10-17 所示)。
图 10-17
在提交窗口中选择一个文件。
然后,显示 Diff 对话框;你可以通过右键点击文件然后选择“显示差异”或者使用键盘快捷键来完成,键盘快捷键是 cmd + D (macOS)或者 CTRL + D (Linux/Windows)。差异对话框如图 10-18 所示。
图 10-18
差异对话框
左边的面板显示了您最后一次提交时的文件,右边的面板显示了现在的文件(包含您的更改)。文件之间的更改或“差异”在右侧面板上以浅绿色显示;该突出显示延伸到左侧面板,以指出差异的位置。
忽略文件
您可能希望将大多数项目文件置于版本控制之下,但是有些文件您可能不希望置于源代码控制之下。您可以在每次提交时过滤掉您不想放在 Git 中的文件——您只需在提交窗口中取消选中它们——但是这将会很麻烦、乏味,并且容易出错(您可能会错过一些东西)。幸运的是,解决方法很简单。
您可以创建一个名为的文件。gitignore 在项目文件夹中的任何地方——但是它通常在项目的根文件夹中。忽略文件是一个简单的文本,其中每行包含一个要忽略的文件或目录的模式。项目中与忽略文件中的模式匹配的任何文件都将被忽略,它们不会是更改列表的一部分。
如图 10-19 右键单击项目,然后选择新建 ➤ 文件,可以在项目根目录下添加一个忽略文件。
图 10-19
将文件添加到项目中
键入文件的名称-。gitignore(如图 10-20 所示)——在新文件对话框中。
图 10-20
新文件
按回车完成动作。
IntelliJ 添加了。gitignore 文件到项目的根目录。由于我们的项目处于版本控制之下,IDE 可能会询问您是否要将新创建的文件添加到 Git 中(如图 10-21 所示)。在这种情况下,是的,我想补充。gitignore 到版本控制。所以,我会选择“添加”
图 10-21
将文件添加到 Git
或者,如果您喜欢在命令行上工作,您可以使用 IntelliJ 的终端,然后创建。gitignore 项目根文件夹中的文件。那也可以。
现在可以开始向忽略文件添加条目了。清单 10-1 中列出了许多 ignore 文件中最常见的一些模式。
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# IntelliJ
out/
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# macOS
.DS_Store
Listing 10-1Git Ignore File
在生成的示例文件中(列表 10-1 ),只有在。意见文件夹被忽略;但是如果你想完全忽略整个。idea 文件夹中,只需将下面一行添加到。gitignore 文件:
.idea/
将文件添加到忽略列表的另一种方法是使用 IntelliJ 中的插件。进入首选项(macOS 中的 cmd +、)或设置(Windows/Linux 中的 CTRL + Alt + S ),然后进入插件。转到“市场”标签,然后搜索“忽略”如图 10-22 所示,我安装了。忽略插件(由 JetBrains 开发)和“添加到 gitignore”(由 euphoricity 开发)——你不必安装这两个插件。大多数开发者只是从 JetBrains 安装插件。
图 10-22
Gitignore 外挂程式
一旦你安装了插件,你可以通过右击项目名称(在项目工具窗口中)来添加一个 Git ignore 文件到项目中——如图 10-23 所示——然后转到新建 ➤ 。忽略文件 ➤ 。gitignore 。
图 10-23
新的。gitignore file 忽略档案
在接下来的屏幕中,您可以从各种配置文件中进行选择。因为我正在做一个 Java 项目,所以我选择了“Java”,如图 10-24 所示。
图 10-24
忽略文件生成器
点击生成完成动作。该插件生成一个忽略文件,并预加载您想在 Java 项目中忽略的最常见的文件和文件夹模式。
图 10-25 显示了生成的忽略文件。
图 10-25
已生成。gitignore 文件
GitHub 集成
GitHub 是 IntelliJ 的一等公民。如果你有一个 GitHub 账户,在 IntelliJ 中集成它是很简单的。
进入首选项(macOS 中的 cmd +、)或设置(Linux/Windows 中的 CTRL + Alt + S ),然后进入版本控制。检查 GitHub 是否存在。GitHub 在 IntelliJ 中是作为一个插件提供的,但它可能是在安装过程中安装的。所以,在大多数情况下,你应该有它——如果没有,就从插件市场安装 GitHub。
如果你有 GitHub 插件(就像我在图 10-26 中看到的),你将有机会在这个对话框中添加你的 GitHub 账户。
图 10-26
首选项 GitHub
单击“添加帐户”链接。它将启动您的默认浏览器,并将您带到 JetBrains 的页面,在那里有一个警告等待您——“只有在 JetBrains IDE 打开该页面时才继续”,如图 10-27 所示。
图 10-27
在 GitHub 中授权
点击“在 GitHub 中授权”按钮继续操作。点击链接会将你带到 GitHub 页面(如图 10-28 所示)。您现在可以授权 JetBrains 访问您的 GitHub 帐户。
图 10-28
授权 JetBrains IDE 集成
点击“授权 JetBrains”完成操作。在短暂地重定向到 JetBrains 站点后,我们会在 GitHub 中看到我们已经被授权的确认,如图 10-29 所示。
图 10-29
确认页面
现在我们回到 IDE。你应该可以在偏好设置窗口的 GitHub 部分看到你的 GitHub 账户,如图 10-30 所示。
图 10-30
首选项➤版本控制➤ GitHub
一旦我们在 IntelliJ 中设置了 GitHub,我们现在就可以开始在 GitHub 中共享任何项目。
在 GitHub 中分享当前打开的项目,你要做的就是进入主菜单栏,然后 Git ➤ GitHub ➤ 在 GitHub 上分享项目(如图 10-31 )。
图 10-31
在 GitHub 上共享项目
在随后的对话框中(图 10-32 ),输入存储库名称——这将默认为 IntelliJ 中的项目名称,但是您可以在这里更改它。我通常不去管它,这样我本地环境中的项目名称就和它在 GitHub 上的名称一样了。您可以添加描述,但这是可选的。
图 10-32
在 GitHub 对话框上共享项目
点击“共享”完成操作。
一旦 IntelliJ 将本地回购完全推送到 GitHub,您将得到一个提示(如图 10-33 所示),其中包含一个指向 GitHub 中项目页面的可点击链接。
图 10-33
在 GitHub 上成功共享项目
点击链接进入该项目的 GitHub 页面。
图 10-34 显示了 GitHub 上的项目。
图 10-34
GitHub 上的共享项目
提交并推送到远程存储库
当我们的项目仅存在于本地回购中时,我们所要做的就是“提交”变更。这已经足够了,因为我们当时没有远程回购,但是因为我们的项目现在托管在 GitHub 中,所以您也需要将本地回购中的变化反映到上游回购中。为此,你现在需要选择“提交并推送”,而不是点击“提交”,如图 10-35 所示。
图 10-35
提交和推送
单击“提交并推送”会提交所有更改并将这些更改推送到上游回购。
创作主旨
GitHub 还有另一个功能,允许其成员共享代码片段,比如 pastebin。com 。这些代码片段被称为 gists。GitHub 在其网站上提供了创建新 gists 的功能。使用 IntelliJ,您可以通过在当前打开的项目中共享源代码来创建 gists。
要开始将您的代码作为要点共享,请在当前打开的项目中选择一个源文件—在项目工具窗口中选择该文件,然后进入主菜单栏,git➤github➤create gist(如图 10-36 所示)。
图 10-36
创建要点
在随后的对话框中(图 10-37 ,您为要点提供文件名;它将默认为 IntelliJ 中的文件名,但是您可以在这里更改它。如果愿意,您可以提供描述。
图 10-37
创建要点
单击确定完成操作。
图 10-38 显示了我们在 GitHub 上发布的要点。
图 10-38
我们新创造的主旨
关键要点
-
源代码控制是现代软件开发的一部分。您需要它来跟踪变更并与团队共享代码。
-
Git 是最流行的源代码控制软件之一。它被广泛使用并定期更新。在 IntelliJ 中使用 Git 很容易。
-
GitHub 是一个流行的远程回购托管网站。在 IntelliJ 中使用 GitHub 也很容易。
-
在 GitHub 中共享一个项目(或者只是片段)在 IntelliJ 中是轻而易举的事情。
十一、测试
在本章中,我们将介绍以下内容:
-
测试
-
单元测试
-
测试基础
-
如何在 IntelliJ 中设置
测试是开发过程中同样重要的一部分。如果你想让你的应用程序被任何重要的人使用(也许是付费用户),那么这个应用程序不能有粗糙的边缘。它不能有任何重大或明显的错误。它需要经过验证和测试。
测试类型
测试有很多种;你将使用哪一个取决于你正在构建的应用程序的类型。如果你正在开发一款游戏,除了通常的功能、集成、开发者和用户验收测试之外,你很可能会包括声音测试、浸泡测试、符合性或一致性测试。假设您正在构建一个企业电子商务系统。在这种情况下,除了漏洞测试之外,你很可能会在性能或压力测试上多花一点时间——测试种类很多。下面简单介绍一些常见的。
功能测试。功能测试是测试应用程序的标准方式。它被称为功能,因为我们正在测试应用程序的特性(也称为功能),因为它们是在需求规范中指定的——需求规范是你或业务分析师在应用程序的规划阶段编写的。需求规格将被写在一个文档中(通常称为功能需求规格)。你可能在功能规范中发现的一个例子是“用户必须在进入应用程序之前登录到服务器”,“用户必须提供有效的电子邮件进行注册”,等等。测试人员,通常称为 QA 或 QC(分别是质量保证和质量控制的缩写),是执行这些测试的人。他们将创建测试资产,制定测试策略,执行它们,并最终报告执行的结果。失败的测试通常被分配给开发人员(您)来修复和重新提交。我在这里描述的是一个开发团队的典型实践,这个团队有一个单独的或者专门的测试团队;如果你是一个人的团队,QA 很可能也是你。测试是一种完全不同的技能,我强烈建议你寻求其他人的帮助,最好是那些有测试经验的人,来帮助你。
性能测试。仅仅从它的名字,你就可以猜到这种测试是做什么的。它将应用推向极限,并观察它在压力下的表现。这里你想看到的是应用程序在高于正常水平的条件下是如何反应的。
浸泡测试或耐久测试。这是一种性能测试;通常,你会让应用程序长时间运行在各种操作模式下,例如,让应用程序在暂停时或在标题屏幕上暂停很长时间。你在这里试图找到的是应用程序如何响应这些条件,以及它如何利用系统资源,如内存、CPU、网络带宽等。;您最有可能使用应用程序分析器来执行这些测量。
音量测试。这是另一种形式的性能测试;如果您的应用程序使用数据库,您可能希望了解当数据加载到数据库时它将如何响应。你要检查的是系统在各种数据负载下的反应。
尖峰测试(或可扩展性测试 ) 。这也是另一种性能测试。如果应用程序依赖于中央服务器,该测试通常会增加连接到中央服务器的用户(设备端点)数量。你需要观察用户数量的激增是如何影响用户体验的:应用程序是否仍能响应,是否对每秒帧数、延迟等有影响。
兼容性测试。在这里,您可以检查应用程序在不同设备和软硬件配置上的表现。
符合性或一致性测试。例如,如果你正在为 Android 开发一个游戏应用程序,这是你对照 Google Play 应用程序或游戏指南检查游戏的地方;请务必阅读位于 https://support.google.com/googleplay/android-developer/answer/10959797?hl=en
的 Google Play 开发者政策中心。确保你也熟悉 PEGI(泛欧游戏信息)和 ESRB(娱乐软件评级委员会)。如果游戏应用程序内容包含不符合特定评级的不良内容,则需要对其进行识别和报告。违规可能是拒绝的原因,这可能导致昂贵的返工和重新提交。如果您正在从用户那里收集数据,您可能需要审核应用程序,以检查它是否符合适用的数据隐私法规。
本地化测试。这一点至关重要,尤其是如果这款应用面向全球市场的话。应用程序标题、内容和文本需要用支持的语言进行翻译和测试。
恢复测试。这将边缘案例测试带到了另一个高度。在这里,应用程序被迫失败,您将观察应用程序在失败时的行为以及失败后如何恢复。它会让你洞察你是否写了足够多的 try-catch-finally 块。应用程序应该优雅地失败,而不是突然失败。只要有可能,运行时错误应该由 try-catch 块来保护;并且当异常发生时,尽量写日志,保存游戏状态。
渗透或安全测试。这也称为漏洞测试。这种测试试图发现应用程序的弱点。它模拟了潜在攻击者为规避应用程序的所有安全功能而进行的活动;例如,如果应用程序使用数据库来存储数据,尤其是用户数据,笔测试人员(进行渗透测试的专业人员)可能会在 Wireshark 运行时使用该应用程序——Wireshark 是一种检查数据包的工具;这是一个网络协议分析器。如果您以明文形式存储密码,它会在这些测试中显示出来。
声音测试。如果你的应用程序使用声音,检查是否有任何错误加载文件;还有,听听声音文件有没有爆裂声等等。
开发者测试。这是你(程序员)在向应用程序添加一层又一层代码时要做的测试。这包括编写测试代码(也用 Java)来测试你的实际程序。这就是所谓的单元测试。这就是本章的全部内容。
单元测试
开发人员以这样或那样的方式测试他们的代码;有些人通过简单地运行应用程序,给它输入一些内容,甚至试图通过在输入框中键入特殊字符来破坏它。他们(开发人员)经常这样做,通常是在他们完成一个方法的编码之后,这是一个自然的停止点,然后他们开始一些测试活动。我们这样做是因为我们想知道应用程序的行为是否与预期一致。更多的时候,我们所做的测试是一种非结构化的测试——如果你愿意这样称呼的话,那就是临时测试。
那么单元测试和特别测试有什么不同呢?我们为什么要为此烦恼呢?
单元测试和特别测试都是由开发人员完成的。他们的相似之处到此为止。单元测试是一种已建立的测试方法,其中对源代码的单个单元(通常是方法)进行测试,以确定测试结果是否与一组预期行为一致。单元测试是自动化的;它不是像特别测试那样手动完成的。自动化测试脚本(通常)由构建应用程序的同一个开发人员编写。
单元测试很简单;这是一个方法可能会做或产生的特定的东西。一个应用程序通常有许多单元测试,因为每个测试都被定义为一组狭窄的行为。所以,你需要大量的测试来覆盖全部的功能。Java 开发人员通常使用 JUnit 来编写单元测试。
JUnit ( https://junit.org/
)是 Kent Beck 和 Erich Gamma 编写的回归测试框架。你可能记得他们分别是创建极限编程的人和来自四人帮(g of,设计模式)的人,以及其他人。
为什么您应该进行单元测试
您需要以某种方式测试您的代码;为什么不遵循一个成熟的测试框架呢?
自动化测试是防止回归和测试代码库中那些边缘案例的最简单的方法——边缘案例通常在特别测试中被忽略。
使用单元测试的另一个令人信服的原因是它给你信心无情地重构你的代码。当您引入代码库的变更时,单元测试会在您破坏某些东西时提醒您。如果您可以信任单元测试,重新认证您的代码就像重新运行测试一样简单。
何时编写测试
这是一个激烈辩论的话题。TDD 的拥护者坚持认为,在编写实际代码之前,应该先编写测试。另一方面,一些开发人员会在编写了大量代码后编写测试。我认为,很多开发人员都介于两者之间(包括你自己)——写一点代码,然后写一点测试。
何时运行测试
您应该尽可能频繁地运行您的测试。一旦您对代码进行了重大的修改,就运行测试。
如果您的团队有一个策略,您应该在一天结束时签入所有代码,那么在签入代码之前运行所有的测试是一个好主意。这是为了确保您的更改不会破坏现有代码。
IntelliJ 中的 JUnit
IntelliJ 对 JUnit 有极好的支持;它在安装过程中安装捆绑的 JUnit 插件。你可以看看 IntelliJ 的首选项 (或者设置) ➤ 插件来验证一下(如图 11-1 )。
图 11-1
JUnit 外挂程式
在 IntelliJ 中,编写 JUnit 测试是一项简单的任务。测试只是一个使用 @Test 注释的类,如清单 11-1 所示的代码。
Note
您可以在 IntelliJ 中使用 JUnit 3、4 或 5。如你所见,对于这一章,我使用了 JUnit5。
import static org.junit.junpiter.api.Assertions;
public class SampleTest {
@Test
void shouldShowSimpleAssertion() {
Assertions.assertEquals(1,1);
}
}
Listing 11-1SampleTest.java
注释@Test 来自 JUnit5 的org.junit.jupiter.api
。Test
。当您用@Test 修饰一个方法时,它就成为了一个测试方法。
我们的测试方法(在清单 11-1 中)还没有测试任何其他的类或方法;我们只是在做一个简单的断言。
断言类来自 Junit5 的 jupiter 库。这个类中的一个方法是 assertEquals() 方法。第一个参数是期望值,第二个参数是实际值。如果第二个参数(实际值)等于第一个参数(预期值),断言返回 true,因此测试通过。
IntelliJ 让我们很容易分辨出哪个参数是期望值,哪个是实际值。IntelliJ 的参数提示(见图 11-2 )将我们从记忆方法参数的位置意义中解放出来。我们不必记住哪个参数是期望值,哪个是实际值。
图 11-2
assertEquals()方法的操作中的参数提示
虽然您可以关闭参数提示,但我建议不要这样做,因为这是一个有用的特性。然而,如果你认为你有一个有效的理由这样做,以下是如何做到这一点:
-
将插入符号放在一个参数提示上——在图 11-3 中,我将插入符号放在“预期的”提示中。
-
使用选项+ ENTER (macOS)或 Alt + ENTER (Linux/Windows)快捷键。
-
将显示一个下拉选项,如图 11-3 所示。
-
选择不显示当前方法的提示。
这将关闭 assertEquals()的参数提示。
图 11-3
关闭参数提示
IntelliJ 将在第一次遇到@Test 注释时对其进行标记。使用常用的代码检查工具即可;使用 option + ENTER (macOS)或 Alt + ENTER (Linux/Windows)将 jUnit5 添加到类路径中(如图 11-4 )。
图 11-4
将 JUnit5 添加到类路径
虽然我们刚刚将 JUnit5 添加到我们的类路径中,但是我们的库中还没有它。在接下来的对话框中(图 11-5 ), IntelliJ 将提供从 Maven 资源库下载它。我想将其下载到我的项目的库文件夹中;因此,我勾选了下载到旁边的框,如图 11-5 所示。
图 11-5
从 Maven 资源库下载库
单击确定完成操作。下载完成后,您会在项目的 lib 文件夹中找到 JUnit5 库(如图 11-6 所示)。
图 11-6
lib 文件夹中的 JUnit5 库
我们需要为断言类添加一个导入语句。您可以使用代码检查快捷键( option + ENTER 或 Alt + ENTER )来快速解决这个问题;选择导入类,如图 11-7 所示。
图 11-7
导入断言类
现在一切正常,我们可以进行测试了。由于我们只有一个测试方法,我将只点击测试方法旁边的绿色箭头(如图 11-8 所示)。
图 11-8
运行 shouldShowSimpleAssertion()
如你所料,我们的测试通过了。
当一个测试成功时,你会在通过测试的测试用例方法和测试类旁边看到绿色的复选标记,如图 11-9 所示。
图 11-9
测试成功
当测试失败时会发生什么?让我想想。编辑 assertEquals()方法,使其看起来像下面的代码:
Assertions.assertEquals(1,2);
当预期值(第一个参数)与实际值(第二个参数)不同时,测试应该会失败。
重新运行测试,不出所料,它失败了。图 11-10 向我们展示了失败测试的结果。
图 11-10
测试失败
失败的测试方法和包含它的测试类旁边的 X 标记表示断言失败。
当您选择失败的测试时(图 11-10 中运行窗口的左面板),测试失败的详细信息显示在右面板。在这里,我们可以看到期望值是 1,实际值是 2 —这就是它失败的原因。assertEquals()方法仅在预期值与实际值相同时返回 true。
测试实际的类
现在我们已经有了足够的关于设置 JUnit 测试的理论和实践知识,让我们在一个实际的类中使用它——您可能想要为此设置一个新的项目。
向新项目添加一个新的 Java 类,并编辑它以匹配清单 11-2 。
public class MainProgram {
String sayYourName() {
return getClass().getName();
}
int addTwoNumbers(int a, int b) {
return a + b;
}
}
Listing 11-2MainProgram
为现有的类创建一个测试类是非常容易的。将插入符号放在类名上,然后按 cmd + N (macOS)或Alt+Insert(Linux/Windows),再选择测试(如图 11-11 )。
图 11-11
生成➤测试
IntelliJ 提示我们“没有找到测试根”(图 11-12 )。理想情况下,您应该在项目中建立一个测试根文件夹,其中包含所有的测试类。由于我们没有这样做,IntelliJ 询问您是否希望源根目录也作为您的测试文件夹。现在,我将单击“确定”。
图 11-12
未找到测试根
点击确定后,弹出创建测试对话框。在这里我们可以输入 IntelliJ 将为我们生成的测试类的一些细节(图 11-13 )。有点问题。在当前模块中找不到 JUnit5——必须为您使用它的每个项目导入 JUnit 5 库。
图 11-13
未找到创建测试➤ JUnit5
单击“Fix”按钮将尝试下载 JUnit5 库并为我们的项目创建一个本地副本。
接下来会弹出“从 Maven 资源库下载库”(图 11-14)——你之前已经看过了,所以你已经知道该怎么做了。
图 11-14
从 Maven 资源库下载库
单击确定完成操作。下载完成后,我们将再次看到“创建测试”对话框(图 11-15 )。
图 11-15
创建测试
类名默认为要测试的类名加上单词“Test”对话框的下部面板包含 MainProgram(要测试的类)的成员方法。您可以检查您想要生成测试的方法—我想要为 sayYourName()和 addTwoNumbers()方法创建测试,所以我检查了它们。
另外,我想为一些设置生成一个存根方法,所以我在框前勾选了setUp/@框。
点击确定按钮,完成生成动作。图 11-16 向我们展示了生成的 MainProgramTest 类和项目的 lib 文件夹,其中现在包含了下载的 JUnit5 库。
图 11-16
项目工具窗口中的 Lib 文件夹
Note
在早期版本的 IntelliJ 中,单词“Test”必须是类名的一部分。这是一个要求。对于当前版本的 JUnit 来说,这不再是真的了——但是按照惯例,我们仍然将“Test”作为类的一部分。
清单 11-3 显示了生成的 MainProgramTest 类。
import static org.junit.jupiter.api.Assertions.*;
class MainProgramTest {
@org.junit.jupiter.api.BeforeEach
void setUp() {
}
@org.junit.jupiter.api.Test
void sayYourName() {
}
@org.junit.jupiter.api.Test
void addTwoNumbers() {
}
}
Listing 11-3MainProgramTest
在生成的 MainProgramTest 上可能有几个错误。它们只是缺少导入语句和类路径错误——如图 11-17 所示。您可以使用代码检查工具( option + ENTER 或 Alt + ENTER )快速解决它们。
图 11-17
将 JUnit5 添加到类路径
一旦您解决了缺少的类路径条目和导入语句,我们现在就可以开始编码实际的测试了。
编辑 MainProgramTest 类,并执行以下操作:
-
向该类添加一个 MainProgram 成员变量(mp)。
-
在 setUp()方法中实例化 mp 成员变量。
您的代码应该类似于清单 11-4 中的代码。
class MainProgramTest {
MainProgram mp = null;
@org.junit.jupiter.api.BeforeEach
void setUp() {
mp = new MainProgram();
}
@org.junit.jupiter.api.Test
void sayYourName() {
}
@org.junit.jupiter.api.Test
void addTwoNumbers() {
}
}
Listing 11-4Add
您可以使用 setUp()方法来实例化测试类的成员变量。还可以使用 setUp()方法连接数据库、打开文件、启动与服务器的连接等。
接下来,让我们为 sayYourName()和 addTwoNumbers()方法添加实际的测试。清单 11-5 显示了 MainProgramTest 类的完整代码。
import org.junit.jupiter.api.Assertions;
class MainProgramTest {
MainProgram mp = null;
@org.junit.jupiter.api.BeforeEach
void setUp() {
mp = new MainProgram();
}
@org.junit.jupiter.api.Test
void sayYourName() {
Assertions.assertEquals("MainProgram", mp.sayYourName());
}
@org.junit.jupiter.api.Test
void addTwoNumbers() {
Assertions.assertEquals(5, mp.addTwoNumbers(3,2));
}
}
Listing 11-5Complete Code for MainProgramTest
清单 11-5 中标记为粗体的语句是您需要编写的语句;这个类的其余部分是为我们生成的。
现在是运行测试的时候了。
完成的主程序测试如图 11-18 所示。
图 11-18
运行 MainProgramTest
您可以运行一个单独的测试—单击第 13 行旁边的绿色箭头将运行 sayYourName()测试;单击第 18 行上的箭头运行 addTwoNumbers()测试。
我想运行所有的测试,所以我将单击第 3 行(MainProgramTest 类)旁边的绿色箭头。
图 11-19 显示了我们测试运行的结果。
图 11-19
主程序测试的测试运行
全是绿色标记。我们所有的测试都通过了。
更多示例
我为这个新例子创建了一个新项目;如图 11-20 所示,相当原始。
图 11-20
新项目
我将为这个项目设置一个合适的测试根文件夹。来自 JetBrains ( www.jetbrains.com/help/idea/testing.html
)的指导是我们需要在创建任何测试类之前建立一个测试根文件夹。在我们之前的例子中,我们不需要创建一个专用的测试根文件夹——而且在大多数情况下,我们做得很好。但是如果你正在做一个重要的项目,最好遵循正确的指导——这就是为什么我们要建立一个测试根文件夹。
IntelliJ 中的文件夹处理方式不同。src 文件夹有一种特殊的处理方式,而测试根文件夹则完全不同。就像我前面说的,最好遵循工具制造者自己的正确指导。
创建项目时,默认情况下已经创建了 src 文件夹,但没有创建 test 文件夹。你必须自己创建它——为此,在项目工具窗口中右击项目名称,如图 11-21 所示。
图 11-21
新目录
选择新的 ➤ 目录,然后提供新的目录名。我们想要创建一个测试根目录,所以我们称之为“测试”——如图 11-22 所示。
图 11-22
新目录名
键入新目录的名称后按 ENTER 键,在项目工具窗口中创建文件夹。
接下来,右键单击新创建的测试目录,选择标记目录为 ➤ 测试源根,如图 11-23 所示。
图 11-23
将目录标记为测试源根目录
现在我们准备编码和测试。让我们从 https://codingbat.com/prob/p159227
中挑选一个简单的热身运动;问题内容如下:
"给定 2 个 int 值,如果一个为负,一个为正,则返回 true。除非参数' negative '为真,否则只有当两者都为负时才返回 true。
因此,在 src 文件夹中,我们添加了一个源文件。你可以通过右击 src 文件夹,并选择新建 ➤ Java 类来实现。把它命名为“波斯内克”编辑它以匹配清单 11-6 。
public class PosNeg {
boolean posNeg(int a, int b, boolean negative) {
boolean retval = false;
return retval;
}
}
Listing 11-6PosNeg Class
这对我们来说应该是一个很好的起点。
让我们创建测试。
前面,我向您展示了如何使用 generate 键盘快捷键来生成测试类。您仍然可以使用它,但我想我会向您展示另一种方法,这一次只使用代码检查快捷方式,我们以前最喜欢的——命令+ ENTER (macOS)或 Alt + ENTER (对于 PC 用户)。
将插入符号放在类名(PosNeg)上——如图 11-24 所示——然后使用代码检查快捷方式。
图 11-24
通过快速修复快捷方式创建测试(command + ENTER)
选择“创建测试”在接下来的屏幕中(图 11-25 ),输入名称 test class 并选择要生成的存根方法——哦,顺便说一下,您需要修复“在模块中找不到 JUnit5 库”的错误。你已经知道怎么做了。
图 11-25
创建测试对话框
单击“确定”完成操作;当它完成时,你应该在测试文件夹中有一个类(如图 11-26 所示)。
图 11-26
生成的 PosNegTest 类
编辑 PosNegTest 类以匹配清单 11-7 。
import static org.junit.jupiter.api.Assertions.*;
class PosNegTest {
PosNeg pn = null;
@BeforeEach
void setUp() {
pn = new PosNeg();
}
@Test
void posNegOneNegativeOneFalse() {
assertEquals(true, pn.posNeg(1,-1,false));
}
@Test
void posNegNegativeOneOneFalse() {
assertEquals(true, pn.posNeg(-1,1,false));
}
@Test
void posNegNegativeFourNegativeFiveTrue() {
assertEquals(true, pn.posNeg(-4,-5,true));
}
}
Listing 11-7PosNegTest Class
我为 posNeg()方法编写了三个测试。详情见表 11-1 。
表 11-1
posNeg()方法的测试用例
|判例案件
|
因素
|
预期结果
|
| --- | --- | --- |
| one | posNeg(1, -1, false) | 真实的 |
| Two | posNeg(-1, 1, false) | 真实的 |
| three | 正负(-4, -5, 真) | 真实的 |
通常情况下,你会为每一个你将要测试的方法准备更多的测试用例。这是因为您希望看到您的代码在各种条件下的行为。理想情况下,您应该涵盖边界条件。在我们简单的测试案例中,当两个输入都为正,两个输入都为负时,我有一个测试;当一个输入为负,另一个输入为正时,我有另一个测试。这不是详尽的报道,但这是一个良好的开端。
让我们进行测试。
图 11-27 显示三个测试都失败了。不奇怪。我们还没有对 posNeg()方法做任何事情。这是一个好的开始。这实际上是你应该开始的地方——一个失败的测试。现在,让我们第一次尝试解决问题。
图 11-27
三次测试失败
编辑 PosNeg 类以匹配清单 11-8 。
public class PosNeg {
boolean posNeg(int a, int b, boolean negative) {
boolean retval = false;
if (negative) {
if ((a * b) < 0) {
// one is positive and the other negative
retval = false;
}
else {
// either they're both positive or negative
if (a < 0) {
// both numbers are negative
retval = true;
}
else {
retval = false;
}
}
}
return retval;
}
}
Listing 11-8PosNeg Class
一点点编码,一点点测试。让我们看看我们的代码是否能让所有的测试用例都通过。重新运行测试类。
图 11-28 显示了我们工作的进度。一次考试通过了,但两次没有通过。
图 11-28
一次测试通过;两次测试失败
如果您点击任何失败的测试(运行窗口的左面板,如图 11-28 所示),详细信息将显示在右面板中。在这里,您可以看到测试方法posnegnegneveroneoneFalse()的预期结果应该是 true,但是我们的测试运行是 false。
因此,虽然我们当前的解决方案已经部分正确,但它在三个测试中有两个失败了。所以,还是多写一点代码,多做一点测试吧。
切换回 PosNeg 类,继续编码,直到通过所有测试。编辑它以匹配清单 11-9 。以粗体突出显示的语句是新添加的内容。
public class PosNeg {
boolean posNeg(int a, int b, boolean negative) {
boolean retval = false;
if (negative) {
if ((a * b) < 0) {
// one is positive and the other negative
retval = false;
}
else {
// either they're both positive or negative
if (a < 0) {
// both numbers are negative
retval = true;
}
else {
retval = false;
}
}
}
else {
retval = ((a * b) < 0);
}
return retval;
}
}
Listing 11-9Complete Code for PosNeg
让我们重新进行测试。
图 11-29 显示了我们测试运行的结果。现在,所有的测试都通过了。
图 11-29
所有测试都通过了
我希望这能让你开始单元测试。我们只是触及了表面。我让您来探索 JUnit 断言类的其他断言方法。
关键要点
-
测试是开发的重要部分。不要吝啬。
-
在 IntelliJ 中设置单元测试非常容易。你没有理由不用它。
-
单元测试建立对代码库的信心。如果你信任测试,你可以毫不留情地重构。当你对代码充满冒险精神时,它就是你的生命线。您可以不受惩罚地试验您的代码;继续运行您的测试,只要您没有破坏任何东西,就继续破解。
-
从一次失败的测试开始——这没什么错。编写一点代码,然后进行一点测试,直到你覆盖了所有的测试用例。
十二、应用
在本章中,我们将介绍以下内容:
-
JavaFX 概述
-
如何设置 JavaFX 并将其包含在项目中
-
如何使用 JavaFX 构建基本的 UI 应用程序
-
如何设置和使用场景构建器
用 Java 构建用户友好的应用程序有三种方法。你可以去
-
Web 应用路线,在这种情况下,你需要了解一些 JakartaEE 应用——附录 A(本书的在线资源)简要讨论了一些常见的 JakartaEE 应用以及如何使用 IntelliJ 构建它们。您可以通过位于
www.apress.com/9781484274453
的下载源代码链接访问本附录。 -
手机应用路线,这种情况下你就需要和安卓打交道了。
-
JavaFX route 是一个技术栈,它将让你构建丰富的桌面应用,这也是我们本章的主题。
简史
JavaFX 并不是 Java 生态系统中 UI 技术的起点。Java 对桌面应用技术的竞标开始得更早。早在 1995 年(Java 的首次亮相),开发人员已经使用 AWT——抽象窗口工具包的缩写——来构建小程序(这在当时是一件大事)和构建桌面应用程序。AWT 的一个限制是它使用了底层操作系统的 UI 控件(这很笨重),而且这也意味着你的应用程序在每个操作系统上看起来(和工作起来)都不一样。
1997 年,Sun Microsystems 推出了 JFC (Java 基础类),更亲切地称为 Swing API。如果您正在构建 Java 桌面应用程序,那么 Swing 就是您要使用的。Swing 大受欢迎,因为与 AWT 不同,它不使用底层操作系统的 UI 控件,这意味着该应用程序在不同平台上的外观和行为都是一致的。
2008 年的某个时候,JavaFX 作为 Swing 的继任者被推出;但是 JavaFX 的历史并不是始于 2008 年,而是更早。
表 12-1 显示了 JavaFX 的时间表。
表 12-1
JavaFX 的历史
|发布日期
|
版本
|
评论
|
| --- | --- | --- |
| 2000 年初 | | SeeBeyond 的克里斯·奥利弗创造了 F3(形式服从功能)。F3 是一种用于开发 GUI 应用程序的脚本语言。 |
| Two thousand and five | | 太阳微系统公司收购 SeeBeyondF3 改名为 JavaFX。 |
| Two thousand and seven | | 在 JavaOne 大会上,Sun Microsystems 发布了 JavaFX。 |
| Two thousand and eight | One | JavaFX 发布了。 |
| Two thousand and nine | One point one | 包括移动支持。 |
| Two thousand and nine | One point two | 2009 年在 Q2 上映。 |
| Two thousand and ten | One point three | 2010 年在 Q2 上映。 |
| Two thousand and ten | 1.3.1 | 将于 2010 年第三季度发布。 |
| Two thousand and eleven | Two | JavaFX 脚本已被删除。JavaFX 现在支持 Java API。对 JavaFX mobile 的支持已取消。幕后发生了许多变化。添加了对惰性绑定、绑定表达式、绑定序列表达式和部分绑定重新计算的支持。另外,JavaFX 现在是开源的。 |
| Two thousand and twelve | Two point one | 现在支持 macOS 桌面。 |
| Two thousand and twelve | Two point two | 将于 2012 年第三季度发布。现在,支持 Linux 了。 |
| Two thousand and fourteen | Eight | 到目前为止,您需要单独下载 JavaFX 才能使用它。从此版本开始,JavaFX 包含在 JDK 中。所以,一旦你安装了 JDK,你就自动拥有了 JavaFX。此外,JavaFX 的版本也有重大变化。从此版本开始,JavaFX 版本将遵循 JDK 的版本号。幕后的变化包括支持 3D 图形、传感器支持、MathML、打印和富文本支持等。 |
| Two thousand and seventeen | Nine | JEP 253 (JDK 增强提案),现在我们可以用 CSS 样式化 JavaFX 了。 |
| Two thousand and eighteen | Eleven | Oracle 从 JDK 中删除了 JavaFX。从这个版本开始,您必须从 JDK 单独下载 JavaFX。 |
| Two thousand and nineteen | Twelve | 2019 年在 Q1 上映。 |
| Two thousand and nineteen | 12.0.1 | 2019 年在 Q2 上映。 |
| Two thousand and nineteen | Thirteen | 2019 年第四季度的某个时候发布。 |
| Two thousand and twenty | Fourteen | 2020 年在 Q1 上映。 |
| Two thousand and twenty | Fifteen | 2020 年第四季度发布。 |
| Two thousand and twenty-one | Sixteen | 2021 年在 Q1 上映。 |
设置
学习新技术的最好方法是开始使用该技术开发应用程序。因此,让我们构建一个使用 JavaFX 的新项目。
从 glouhqhttps://gluonhq.com/products/javafx/
为您的操作系统下载 JavaFX SDK。将其解压缩到您喜欢的位置,例如/Users/username/javafx-sdk-16。
创建一个 JavaFX 项目。在新建项目对话框上(图 12-1 ,选择 JavaFX 。
图 12-1
创建新的 JavaFX 项目
为项目命名,就像您过去创建的其他项目一样。单击“下一步”按钮继续操作。
您将被要求从 Maven 资源库下载 javafx-fxml 库(图 12-2 )。
图 12-2
从 Maven 资源库下载 JavaFX 库
下载该库,使其成为项目的一部分;单击“确定”按钮完成操作。
IntelliJ 创建项目。如图 12-3 所示,它创建了三个文件。
图 12-3
新 JavaFX 项目
接下来从主菜单栏进入文件 ➤ 项目结构 ➤ 项目,如图 12-4 所示。
图 12-4
项目结构|项目 SDK
将项目 SDK 设置为 11 或更高;在我的例子中,我将它设置为 OpenJDK 16。
当您仍在项目结构对话框中时,转到库。正如你在图 12-5 中看到的,我们项目的 lib 文件夹中还没有任何东西。在我们的应用程序中使用 JavaFX 之前,我们需要将 JavaFX 库放在这里。
图 12-5
项目结构|库
点击加号添加一个新的库(如图 12-6 )。
图 12-6
项目结构|库|新项目库
从下拉菜单中选择 Java 。
一个文件浏览器(或者说是 Finder,对于 macOS 来说)会弹出来。现在,导航到解压 JavaFX SDK 的位置,指向 lib 文件夹,如图 12-7 所示。
图 12-7
选择 JavaFX 的 lib 文件夹
点击打开按钮完成动作。
IntelliJ 将询问您在哪里添加(哪个模块)JavaFX 库。我的项目中只有一个模块,所以我将选择它(图 12-8 )。
图 12-8
选择模块
单击“确定”按钮完成操作。
您将返回到项目结构对话框。你应该在项目的库部分看到 JavaFX 库,如图 12-9 所示。
图 12-9
项目结构|库
如果您试图在此时运行项目,您将得到一个运行时错误——“Java FX 运行时组件丢失”,如图 12-10 所示。
图 12-10
运行时错误
为了解决这个问题,我们需要向 VM 添加一些选项;为此,我们需要修改运行时配置。
你可以从主菜单栏修改运行时配置,然后进入运行 ➤ 编辑配置。或者,您可以点击编辑器栏上的运行按钮(如图 12-11 ),然后选择修改配置。
图 12-11
运行|修改运行配置
点击“修改”链接,如图 12-12 所示。
图 12-12
编辑运行配置|修改选项
选择添加 虚拟机选项,如图 12-13 所示。
图 12-13
编辑运行配置|修改选项|添加虚拟机选项
在虚拟机选项文本字段(图 12-14 )上,键入以下内容:
图 12-14
运行/调试配置|虚拟机选项
--module-path /path/to/javafx-sdk-16/lib --add-modules javafx.controls,javafx.fxml
不要忘记将 /path/to/javafx-sdk-16 替换为解压 javafx 的实际目录路径。
在我的例子中,我在/Users/ted/Prog tools/JavaFX-SDK-16 中安装了 Java FX,所以这就是我在我的 VM 选项中使用的(如图 12-15 所示)。
图 12-15
编辑运行配置|虚拟机选项
单击“确定”按钮完成操作。
图 12-16 显示了我们运行时的第一个 JavaFX 应用。
图 12-16
JavaFX 应用正在运行
舞台、场景和节点
JavaFX 使用舞台、场景和节点等术语。
将舞台对象想象成一个真实的舞台——人们在那里表演戏剧,就像在剧院舞台上一样。舞台是所有场景(我们仍在剧院类比)将被执行的地方;每个场景将包含不同的设置,旨在执行特定的行为。每个场景都有一套不同的道具——一个可能有假的树,另一个可能有假的波浪,等等。
这样思考 JavaFX 应用程序是有帮助的(使用剧院舞台类比),因为它实际上有点像这样。一个场景只属于一个阶段;每个场景都会有一套不同的道具。
我现在将停止使用剧院类比,这意味着从这一点开始,当我说 stage 时,我指的是 JavaFX stage,当我说 scene 时,我指的是 JavaFX scene。
阶段对象是顶级容器。它包含了整个应用程序。一个场景只属于一个阶段。我们可以说舞台是场景的容器。
场景通常包含子组件;在 JavaFX 术语中,这些组件称为节点。我们可以说场景是节点的容器。节点是放置在场景中的元素。这些节点是 GUI 元素,例如,文本框、复选框、按钮等。
每个节点要么是一个分支节点(意味着它可以有孩子),要么是一个叶节点(意味着它不能有孩子)。场景上的节点集合形成一个树形结构,称为场景图(图 12-17 )。
图 12-17
场景图
在图中,树上的第一个节点被称为根节点。它没有父母。您将在 JavaFX 中使用的每个元素都是一个节点的实例(节点是一个类)。
JavaFX API 定义了几个可以作为根、分支或叶节点的类。分支节点的例子可以是 HBox、StackPane、BorderPane、Group、Region、GridPane 等。—这些类通常是布局类。叶节点的一些例子是文本框、矩形、滑块、单选按钮、密码字段、分隔符、工具提示等。
当用实际的类名替换时,这个数字可能类似于实际应用程序中的某个东西。
在一个实际的应用程序中,场景图可能如图 12-18 所示。
图 12-18
应用程序的场景图
你好世界
让我们回到我们的“Hello World”示例项目。
在主编辑器的选项卡中选择 sample.fxml 文件(图 12-19 )。
图 12-19
sample.fxml
FXML 文件是一种基于 XML 的用户界面标记语言(由 Oracle 公司创建),用于定义 JavaFX 的用户界面。虽然可以通过编程定义场景中的所有节点来构建 JavaFX 应用程序,但这是一项繁琐的工作。产生的代码也很难维护。FXML 是为 JavaFX 构建 ui 的首选替代方法。
创建 JavaFX 项目时,会自动生成三个文件—Main.java、Controller.java 和 sample.fxml 。
编辑 sample.fxml 以匹配清单 12-1 。
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TextField?>
<HBox>
<Label text="User name"></Label>
<TextField></TextField>
<Button text="Login"></Button>
</HBox>
Listing 12-1sample.fxml
即使没有进一步的解释,您也可以理解前面的代码是怎么回事。
前三行是导入语句。它们的功能与我们在 Java 源文件中的功能非常相似。语法有点奇怪,因为每个语句都用一对尖括号和问号括起来——但这就是 FXML 文件。
我们知道 HBox 是一个分支或父容器,所以 Label、TextField 和 Button 节点都包含在 HBox 中,这本能地告诉我们这三个叶节点是 HBox 的子节点。
重新运行该项目会得到如图 12-20 所示的结果。
图 12-20
你好世界
JavaFX 应用程序的生命周期
所有 JavaFX 应用程序都应该扩展类Java FX . application . application类。实例化后,JavaFX 应用程序对象将经历以下生命周期:
-
构造指定应用程序类的实例。如果你定义了一个自己的构造函数,它里面的任何代码都会被调用。
-
运行时调用应用程序的
init()
方法。如果您的应用程序进行任何 HTTP、数据库或 I/O 调用,这可能是放置初始化代码的好地方。 -
运行时调用
start()
方法。此方法通常是在创建 JavaFX 项目时为您生成的。在这里,FXML 被展平为 Java 对象以形成场景图,场景被设置为 stage,并且调用了Stage.show()
方法。 -
运行时会等待应用程序完成,这种情况会在以下任一情况发生时发生:
-
应用程序调用 Platform.exit()。
-
最后一个窗口被关闭,并且
Platform
上的implicitExit
属性为真——这通常发生在您单击窗口上的关闭按钮时。
-
-
运行时调用
stop()
方法。如果您打开了任何 I/O 资源,如网络、数据库或文件资源,这是确保它们关闭的绝佳时机。
Main.java
现在我们对 JavaFX 应用程序的组成有了一些了解,让我们重新看看Main.java源文件。清单 12-2 显示了对【Main.java】的的注释解释。
| -什么 | 我们扩展了`javafx.application.Application`类。所有 JavaFX 应用程序都继承自该类。 | | ➏ | 在运行时,VM 仍然使用静态的`main()`作为入口点。从`main(),`我们调用`launch()`方法,传递任何命令行参数给它(如果我们有的话)。 | | ➋ | 运行时调用`start()`方法并传递一个 stage 对象作为参数。 | | ➌ | 创建一个父节点对象(这是根变量)。它通过将 *sample.fxml* 的内容展平到一个场景图中来填充。 | | -你好 | 场景对象附加到舞台上。 | | ➎ | 最后,运行时调用 stage 对象的`show()`方法。此时,应用程序变得可见。 |import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application { ➊
@Override
public void start(Stage primaryStage) throws Exception{ ➋
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml")); ➌
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275)); ➍
primaryStage.show(); ➎
}
public static void main(String[] args) { ➏
launch(args);
}
}
Listing 12-2Main.java
场景构建器
虽然使用 FXML 而不是通过 API 来定义 UI 元素很容易,我应该说是“更容易”,但这仍然很乏味,尤其是当 UI 变得越来越复杂时。我们可以用来组成 UI 元素的可视化编辑器仍然是理想的工具。这就是为什么我们有场景生成器工具。
Scene Builder 是一个可视化合成工具,我们可以用它来构建 FXML 文件。Oracle 最初创建了它,但出于某种原因,他们停止了对 Scene Builder 的支持。幸运的是,Scene Builder 是开源的,因此,另一个组织(Gluon)取得了所有权。
如果要使用场景构建器,您需要单独安装它;这是一个直观地编写 FXML 文件的便利工具。像任何可视化合成工具一样,您可以简单地拖放元素来构造 ui,编辑其属性,并查看元素在运行时的可视化预览。顺便说一下,Scene Builder 是使用 JavaFX 本身构建的;这就是它能在所有平台上运行的原因。
要使用场景生成器,我们需要从 https://gluonhq.com/pDownload Scene Builderroducts/scene-builder/
下载(图 12-21 )。
图 12-21
场景构建器下载页面
为您的平台选择安装程序(图 12-22 ,然后点击下载按钮完成操作。
图 12-22
场景构建器下载链接
运行安装程序,并按照提示完成。启动场景构建器应用程序;图 12-23 显示了带有未命名项目的场景构建器应用程序。
图 12-23
场景生成器|无标题项目
构建 FXML 文件
让我们使用场景构建器构建一个简单的 UI。
Scene Builder 提供了一些很棒的 UI 入门模板。如果你点击场景构建器的主菜单栏,然后转到文件➤新建模板,你将从一个预建的用户界面模板中选择(如图 12-24 所示)。这是一个很好的开始方式。您可以简单地编辑或删除您不需要的 UI 组件,并从那里继续。
图 12-24
场景构建器模板
但我们不会走那条路。我们将从头开始。
在图 12-23 中,场景构建器的中间面板就是我们的画布。我们只需在这个区域拖放 UI 组件。
我们首先需要一个容器。所以,打开手风琴(左面板,如图 12-25 )到容器,然后点击 VBox。
图 12-25
将 VBox 拖到画布上
在 VBox 上按住鼠标的同时,将其拖到画布上(这里显示“将库项目拖到这里”)。您应该在可视化编辑器中看到 VBox 小部件(图 12-26 )。
图 12-26
VBox 已添加
接下来,向 VBox 添加一个标签。打开手风琴控件到控件,然后选择标签(如图 12-27 )。
图 12-27
添加标签
使用与将 VBox 添加到画布相同的技术,将标签拖放到 VBox 中。
然后,添加一个文本字段和一个按钮。你应该有类似图 12-28 的东西。
图 12-28
标签、文本字段和按钮
如果您想要更改 UI 元素的特定属性,您可以在编辑器中选择它们,然后转到 Properties 部分。您可以更改属性,如对齐、字体、颜色或文本属性——在我的例子中,您可以在图 12-29 中看到。
图 12-29
如何编辑属性
如果您现在保存这个文件并使用纯文本编辑器打开它,您将看到类似于清单 12-3 中的内容。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label text="Label" />
<TextField />
<Button mnemonicParsing="false" text="Button" />
</children>
</VBox>
Listing 12-3sample.fxml
您可以将它复制并粘贴到我们之前的“Hello World”应用程序的 sample.fxml 文件中,这样就可以工作了。考虑到 Scene Builder 和主要 ide(包括 IntelliJ)之间的集成质量,一些开发人员更喜欢这种工作流。
为场景构建器配置 IntelliJ
要在 IntelliJ 中打开 FXML 文件(可视化),我们需要告诉它在哪里可以找到 Scene Builder 应用程序。
打开首选项对话框(或者设置,对于 PC 用户来说),然后进入语言和框架,再进入 JavaFX 。参见图 12-30 。
图 12-30
首选项|语言和框架| JavaFX
您需要指向场景构建器应用程序的安装位置。在 macOS 中,这个位置一般是/Applications/scene builder . app;在 Windows 10 中,默认位置是C:\ Users \ user \ AppData \ Local \ scene builder . exe。
图 12-31 显示了场景构建器应用程序,指向它在/Applications 文件夹中的位置。
图 12-31
找到场景构建器应用程序的位置
单击“打开”按钮确认选择。
你应该返回到场景构建器路径被填充的首选项对话框,如图 12-32 所示。
图 12-32
场景构建器的路径
单击“确定”按钮完成操作。
在场景构建器中打开文件
当你打开一个。fxml 文件在编辑器中,编辑区下面有两个标签页(如图 12-33 )。
图 12-33
FXML 编辑器选项卡
文本区域允许您编辑代码中的标记。
场景构建器选项卡打开。场景构建器中的 fxml(图 12-34 )。
图 12-34
IntelliJ 中的场景生成器
至此,我们结束这一章;但是让我带着一句警告离开。您需要设定您对场景构建器与 IntelliJ 配合使用的预期。在撰写本文时,IntelliJ 对 Scene Builder 的支持有点不稳定——大多数时候,它可以工作,但也有不工作的时候;两者我都经历过。
大多数情况下,Scene Builder 与 IntelliJ 集成的问题是 GUI 编辑器不会在 IntelliJ 中显示,但文本标记可以正常工作。我一直在使用 JetBrains 的问题跟踪( https://youtrack.jetbrains.com
)来跟踪这个问题,这个问题仍然没有结束(在撰写本文时)。希望在 Scene Builder 和 IntelliJ 的未来版本和更新中解决这个问题。
关键要点
-
如果您需要构建跨平台的桌面应用程序,JavaFX 是一个不错的技术选择。
-
您可以通过 API 构建 JavaFX 应用程序,但这很繁琐。请改用 FXML 文件来定义 UI。
-
您可以手工构建 FXML,但这也很繁琐;请使用可视化工具,如场景构建器。
-
如果你喜欢 JavaFX,你可以在
https://openjfx.io/
和https://gluonhq.com/
获得更多关于这项技术的信息。