idea使用帮助文档19(教程)

本文围绕IntelliJ IDEA展开,介绍了配置通用任务服务器、使用Chronon调试、代码部署、文件监视器设置、重构、TODO示例应用、使用TextMate包、将Emacs设为外部编辑器以及将其作为Vim编辑器等功能的详细步骤和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

配置通用任务服务器 

IntelliJ IDEA支持与开箱即用的许多任务跟踪器集成。但是,如果您使用IntelliJ IDEA尚不支持的跟踪器,您仍然可以集成它来配置所谓的通用服务器。

本教程描述如何:

  • 作为通用服务器连接到JIRA Cloud

  • 获取分配给您的问题列表

  • 对于每个问题,请在创建和更新问题时获取其ID,标题,说明,日期和时间

 

在开始配置与智能设备的连接之前,请注意IntelliJ IDEA:

  • 仅支持使用REST API的服务。

  • 支持 基本HTTP身份验证或向服务器发送初步请求。

  • 支持GET和POST请求。

  • 不支持服务器响应中的分页。

指定服务器URL和凭据 

  1. 在“ 设置/首选项”对话框(Ctrl+Alt+S)中,转到“ 工具”| 任务| 服务器。

  2. 单击添加按钮并选择Generic。

  3. 在“ 常规”选项卡上,指定任务跟踪器的URL,连接凭据,然后选中“ 使用HTTP身份验证”复选框。

    指定服务器URL和凭据

     

{serverUrl}变量代表您在“ 常规”选项卡上指定的URL 。

请注意,当您使用HTTP身份验证时,将禁用“ 登录URL”字段。

配置服务器设置 

  1. 切换到“ 服务器配置”选项卡。

  2. 在“ 任务列表URL”中,输入从服务器获取问题的URL。您可以使用变量或输入完整的URL:

    {serverUrl} / rest / api / 2 / search 或 https://serverurl.atlassian.net/rest/api/2/search

  3. ?jql={JQL_Query}表达式添加到任务列表URL: {serverUrl} / rest / api / 2 / search?jql = {JQL_Query}。

    配置服务器设置

     

  4. 单击窗口底部的“ 管理模板变量 ”以配置 JQL_Query变量。

  5. 单击添加按钮右上角的。

  6. 在新字段中,指定变量name(JQL_Query),并添加其值(assignee = currentUser() and resolution = Unresolved)。
    这将使您获得分配给您的未解决的问题。

  7. 单击确定。

    指定模板变量

     

选择器可帮助您检索有关任务的特定信息。前三个选择器是强制性的:

  • tasks:服务器响应中的任务路径(根元素)。

  • id:服务器响应中任务ID的相对路径。

  • 摘要:服务器响应中任务标题的相对路径。

配置响应类型并指定选择器 

  1. 在“ 服务器配置”对话框中,选择JSON响应类型。

  2. 在表中指定选择器以获取问题的ID和标题,并获取其描述。您还可以了解创建和更新问题的日期和时间:

    • 任务: $.issues

    • ID: key

    • 摘要: field.summary

    • 描述: field.description

    • 更新: field.updated

    • 创建: field.created

  3. 单击“ 测试”以确保正确配置所有参数。

    配置响应类型并指定选择器

     

从服务器上传问题 

  1. 单击任务组合,然后选择“ 打开任务”。IntelliJ IDEA将从服务器加载与您的配置匹配的所有问题。

  2. 从列表中选择所需的问题。

  3. 按Ctrl+Q打开问题说明并确保获得所有必需的详细信息。

使用Chronon进行调试 

IntelliJ IDEA支持与开箱即用的许多任务跟踪器集成。但是,如果您使用IntelliJ IDEA尚不支持的跟踪器,您仍然可以集成它来配置所谓的通用服务器。

本教程的内容是什么 

本教程旨在逐步引导您使用Chronon,记录器和“时间旅行”调试器调试Java应用程序。

Chronon记录更改由应用程序在执行时进行。录音保存到文件中。您可以稍后播放这些录音并在团队成员之间分享。

在你开始之前......  

首先,必须要了解Chronon不是字面上的调试器 - 它只能帮助您记录执行进度然后再播放,就像录像带一样。

其次,确保:

  • 您的IntelliJ IDEA版本为13.1或更高版本。本教程适用于14.1版。

  • 下载并安装 Chronon插件。

第三,请注意不同键盘图上的键盘快捷键可能有所不同。本教程使用默认的keymap。

初步步骤 

准备一个例子 

让我们看看Chronon如何处理一个双线程类的简单示例。一个线程执行快速排序,而第二个线程执行冒泡排序。

首先,按照创建第一个Java应用程序页面中的描述创建项目。

接下来,创建一个名为demo的包,最后,将Java类添加到此包中。第一个类称为ChrononDemo.java,它执行双线程数组排序:

 

package demo;

import org.jetbrains.annotations.NotNull;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Random;

public class ChrononDemo {

     public static final int SIZE = 1000;
     public static final Random GENERATOR = new Random();

     public static void main(String[] args) throws InterruptedException {
            final int[] array = new int[SIZE];
            for (int i = 0; i < SIZE; i++) {
                array[i] = GENERATOR.nextInt();
            }
            final Thread quickSortThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    QuickSort.sort(Arrays.copyOf(array, array.length));
                }
            }, "Quick sort");

            final Thread bubbleThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    BubbleSort.sort(Arrays.copyOf(array, array.length));
                }
            }, "Bubble sort");

            quickSortThread.start();
            bubbleThread.start();

            quickSortThread.join();
            bubbleThread.join();
            }
            }

第二个是QuickSort.java类,它执行快速排序:

 

package demo;

class QuickSort {
      private static int partition(int arr[], int left, int right) {
            int i = left, j = right;
            int tmp;
            int pivot = arr[(left + right) / 2];

            while (i <= j) {
                while (arr[i] < pivot)
                    i++;
                while (arr[j] > pivot)
                    j--;
            if (i <= j) {
                tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
                i++;
                j--;
              }
            }

            return i;
       }

        public static void sort(int arr[], int left, int right) {
              int index = partition(arr, left, right);
              if (left < index - 1)
                    sort(arr, left, index - 1);
              if (index < right)
                    sort(arr, index, right);
             }

        public static void sort(int arr[]) {
            sort(arr, 0, arr.length - 1);
        }
}

最后,第三个是 执行冒泡排序的BubbleSort.java类:

 

package demo;

public class BubbleSort {
    public static void sort(int[] arr) {
           boolean swapped = true;
           int j = 0;
           int tmp;
           while (swapped) {
                swapped = false;
                j++;
                for (int i = 0; i < arr.length - j; i++) {
                    if (arr[i] > arr[i + 1]) {
                        tmp = arr[i];
                        arr[i] = arr[i + 1];
                        arr[i + 1] = tmp;
                        swapped = true;
                    }
                }
            }
        }
    }

顺便说一句,建议手动输入代码,以查看魔术IntelliJ IDEA的 代码完成情况。

安装插件 

打开“ 设置/首选项”对话框。为此,请单击设置主工具栏上的,或按Ctrl+Alt+S。

然后单击页面插件

在此页面中,单击“ 安装JetBrains插件 ”按钮,从JetBrains存储库下载并安装插件。在Browse JetBrains Plugins对话框中,找到Chronon插件 - 您可以在过滤器区域中键入搜索字符串:

安装Chronon插件

安装插件并重新启动IntelliJ IDEA以使更改生效。

对UI的更改

重启后,请注意以下更改:

  • 主用工具栏上显示“使用Chronon专用运行”图标。到目前为止,此图标已禁用 Chronon被禁用。一旦出现相应的运行/调试配置
    ,它将Chronon已启用立即启用。

  • Chronon工具窗口(在使用Chronon启动运行/调试配置或打开Chronon记录时可用)。

  • Chronon选项卡出现在Application类型的运行/调试配置中(以及其他一些类型):

    Chronon标签

     

  • 运行 菜单扩展了两个命令:

    • 使用Chronon运行<run / debug configuration name>

    • 打开Chronon录音

     

    Chronon菜单

     

创建运行/调试配置 

要启动我们的应用程序,我们需要运行/调试配置。让我们 创建一个

在主菜单上,选择“运行”| 编辑配置,然后在“运行/调试配置”对话框中单击添加按钮。我们将创建Application类型的新运行/调试配置 ,因此选择以下类型:

选择运行/调试配置的类型

将显示基于“应用程序”类型的新运行/调试配置。到目前为止,它是未命名的,并且缺少对使用main方法的类的引用。让我们指出缺失的信息。

首先,为此运行/调试配置命名。就这样吧ChrononDemo。接下来,按下Shift+Enter并找到包含main方法的名为ChrononDemo.java的类 。这个类位于包中demo

运行/调试配置

定义包含/排除模式

接下来,单击Chronon选项卡。在此选项卡中,您必须指定IntelliJ IDEA应查看的类。这是通过包含/排除模式完成的。在“ 包含模式”区域中,单击 添加一个类

选择要添加的类

现在应用更改并关闭对话框。初步步骤已完成。

使用Chronon运行 

好的,是时候启动我们的应用程序了。为此,请单击Chronon图标主工具栏上的Chronon按钮 ,或选择 Run | 在主菜单上使用Chronon运行ChrononDemo。

让我们选择第一种方式:

运行Chronon应用程序

IntelliJ IDEA显示进度条,然后显示“运行”工具窗口,您可以在其中查看Chronon消息:

Chronon工具窗口

请务必注意,当您通过单击终止应用程序时,不会创建Chronon记录 终止应用程序。如果需要停止应用程序并仍具有Chronon记录,请单击退出按钮“运行”工具窗口工具栏上的“ 退出”按钮。

然后出现Chronon工具窗口。它看起来非常像Debug工具窗口。在此工具窗口中,您可以看到Chronon创建的记录; 这样做,每个记录显示在自己的选项卡中:

Chronon在Chronon工具窗口中记录

打开现有记录 

顺便说一下,如果要打开以前的记录之一,请使用Run | 在主菜单上打开Chronon录音,然后选择所需的录音:

打开Chronon记录

你能用记录做什么? 

在Chronon工具窗口中,您可以:

在线程之间切换 

这很简单 - 只需切换到Threads选项卡,然后双击您感兴趣的线程。所选线程在线程列表中以粗体显示; 除此之外,有关当前所选线程的信息显示在Chronon工具窗口的右上角:

查看主题

逐步完成应用程序 

实际上,您可以使用“运行”菜单的步进命令或“Chronon”工具窗口的步进按钮。与仅允许前进的调试器不同,Chronon还可以反向逐步执行应用程序:

走向相反的方向

因此,除了传统的步进按钮外,还有Step Backwards按钮退后一步Run Backwards to Cursor按钮 向后运行到光标

使用书签 

假设您已停在某一行,例如,在ChrononDemo.java类的main方法中 :

Chronon书签

你想用它的事件编号记住这个地方,以便能够从任何其他地方返回它。这是“ 书签”选项卡变得有用的地方。切换到此选项卡,然后单击 添加按钮。创建当前事件,线程和方法的书签:

新创建的书签

在这样做时,书签会记住事件编号,线程和方法名称。接下来,当您在代码的不同位置时,在“ 书签”选项卡中单击此书签将返回到此特定位置。

探索方法 

如果查看编辑器,您会注意到恢复方法声明旁边左侧装订线中的图标。将鼠标指针悬停在这样的图标上会显示一个工具提示,其中包含已记录的呼叫数。

但是,如果要查看特定的调用事件,请在“ 线程”选项卡中选择所需的 线程(请记住 - 所选线程显示在Chronon工具窗口的右上角),切换到“ 方法历史记录”选项卡,然后跟踪方法的执行历史:

方法历史

因此,您可以使用输入和输出数据探索方法执行,这样可以轻松查看方法的调用方式和位置。

记录值 

什么是Logging选项卡?默认情况下,它为空。但是,使用此选项卡可以定义自定义日志记录语句并在应用程序运行期间跟踪其输出。

这是日志记录的工作方式。在编辑器中,右键单击感兴趣的语句,然后从上下文菜单中选择 Add logging statement:

记录声明

然后,在打开的对话框中,按以下格式指定要监视的变量:

指定要监视的变量

接下来,要使用此日志记录语句,请单击重新运行按钮“ 日志记录”选项卡的工具栏中的 。在“日志记录”选项卡的右侧,显示已记录语句的输出:

记录语句的输出

请注意,此类日志记录等效于向应用程序添加输出语句; 你可以补充一下

 

System.out.println(<variable name>);

但是,这将需要应用程序重建和重新运行。通过Chronon的测井设备,可以避免这种并发症。

探索异常 

假设您想了解异常发生的方式和时间。“ 例外”选项卡显示应用程序执行期间发生的所有异常:

Chronon例外

如果双击异常,IntelliJ IDEA将直接带您到异常发生的位置:

检查异常发生的位置

摘要 

你已经学会了如何:

  • 下载并安装IntelliJ IDEA的Chronon插件

  • 使用Chronon录制启动应用程序。

  • 打开现有的Chronon录音。

  • 使用Chronon工具窗口。顺便说一句,请参阅调试工具窗口参考的 隐藏/恢复工具栏部分,以了解如何显示/隐藏选项卡。

在IntelliJ IDEA中部署 

本教程旨在逐步指导您使用IntelliJ IDEA配置代码的管理部署到远程主机。

在你开始之前 

确保:

  • 您正在使用IntelliJ IDEA 15.0或更高版本。本教程是使用IntelliJ IDEA 2016.1编写的。

  • 您可以访问希望部署代码的远程主机。

另请注意,本教程是在Windows 10上创建的,并使用默认的键盘快捷方式。如果您在不同的平台上工作,或使用其他键盘方案,键盘快捷方式将有所不同。

配置部署服务器 

单击 设置/首选项图标 主工具栏或按 Ctrl+Alt+S 以打开“ 设置/首选项” 对话框,然后选择“ 部署” 页面(您可以通过选择 主菜单上的“ 工具”|“部署”|“配置”来访问同一页面)。

单击新增项目,然后在“ 添加服务器” 对话框中,键入服务器名称(MyRemoteServer)并选择其类型(在我们的示例中,这是“ 本地”或“已装入的文件夹”):

添加服务器对话框

好的,新服务器已添加,但它仍然无效......它只显示Web服务器URL http:// localhost,您将在其中实际浏览上传的文件。

“连接”选项卡中指定了什么? 

选择将上载项目文件的目录。在我们的例子中,这是 C:\ xampp \ htdocs 本地文件夹。您可以手动键入路径,也可以按 Shift+Enter 打开“ 选择路径”对话框。)

部署连接选项卡

“映射”选项卡中指定了什么? 

接下来,切换到Mappings选项卡。默认情况下,“ 本地路径” 字段包含项目根目录的路径。但是,您可以选择项目树中的任何其他目录。我们假设默认值。

在“ 部署路径”字段(默认情况下为空)中,指定服务器上的文件夹,其中IntelliJ IDEA将从“ 本地路径” 字段中指定的文件夹上载数据 (在此示例中,它是ij \ MetersToInchesConverter )。此路径是相对于文件夹指定的)。此路径是相对于文件夹 C:\ xampp \ htdocs指定的。

最后,让我们接受Web路径的默认值/值:

部署映射选项卡

好的,应用更改,服务器就可以使用了。

浏览远程主机 

要确保服务器已启动并运行,请选择“ 工具”| 部署| 在主菜单中浏览远程主机,并 在IntelliJ IDEA窗口右侧显示远程主机工具窗口:

远程主机工具窗口

部署工具 

接下来,让我们执行一些操作,看看会发生什么。

正在上传 

首先,让我们将其中一个文件上传到远程服务器。

在“ 项目工具”窗口中,右键单击要上载的文件。在我们的例子中,让它成为文件MetersToInchesConverter。从上下文菜单中,选择Upload to MyRemoteServer,然后查看上载结果。

部署上传

您还可以上载项目中每个目录的内容。例如,右键单击该目录的父目录MetersToInchesConvertersrc 然后选择“ 部署” 从上下文菜单上传到MyRemoteServer。我们现在将整个目录上传到服务器:

部署文件传输

比较远程和本地版本 

该文件有本地和远程副本 MetersToInchesConverter,它们是相同的。我们来修改本地版本。

要做到这一点,将插入符号放在方法声明中,然后按 Ctrl+Shift+Alt+T(或在主菜单上选择 Refactor | Refactor This)。弹出菜单显示当前上下文中可用的所有重构。让我们选择重命名重构, 并重命名一个方法

重命名方法

执行重构并查看方法名称及其用法已更改。

现在我们已经改变了本地版本。让我们确保IntelliJ IDEA了解这些变化。为此,请转到“ 远程主机工具窗口”工具窗口,然后单击鼠标右键MetersToInchesConverter。从上下文菜单中,选择“ 与本地版本比较”。IntelliJ IDEA打开差异查看器。

差异查看器

正在下载 

在“ 远程主机工具窗口”工具窗口中,右键单击该文件 MetersToInchesConverter,然后从上下文菜单中选择“ 从此处下载”。IntelliJ IDEA显示警告:

部署下载警告

点击继续:

部署下载文件传输

如果先前已将目录上载到服务器,您还可以下载整个目录。例如,如果单击父src目录并选择相同的命令,则将从服务器下载所有嵌套文件。

同步更改 

做一个初步步骤 - 将更改回滚到 MetersToInchesConverter 文件(Ctrl+Z)。您再次MetersToInchesConverter使用重命名的方法查看该类 。

接下来,单击MetersToInchesConverter,然后在主菜单中选择“ 工具”| 部署| 与部署到MyRemoteServer同步:

部署同步

IntelliJ IDEA显示差异查看器,您可以在其中接受个别更改或拒绝它们。

自动上传到默认服务器 

当您需要在服务器上拥有与IntelliJ IDEA项目中完全相同的文件时,自动上传可能会有所帮助。自动上载意味着每当IDE发生更改时,它都将部署到默认部署服务器。

将服务器定义为默认值 

如果在自动上载更改的文件期间默认应用其设置,则部署服务器将被视为默认服务器。要将部署服务器定义为默认服务器,请按照下列步骤操作:

  1. 在“ 部署”页面上选择所需的服务器(在我们的示例中为 MyRemoteServer)。您可以通过两种可能的方式打开此页面: 设置/首选项| 构建,执行,部署| 部署或 工具| 部署| 在主菜单上配置。

  2. 点击用作默认按钮 。

启用自动上传 

设置默认服务器后,您可以自动上传到此服务器。这可以通过以下两种方式完成:

  • 打开部署选项 (主菜单上的设置/首选项|部署|选项或 工具|部署|选项),然后在“将 更改的文件自动上载到默认服务器”字段中选择“ 始终 ”或“显式保存操作”。在字段描述中解释了这两种选择之间的差异。

  • 在主菜单中,选择工具| 部署| 自动上传。请注意,在这种情况下,自动上传是在“ 始终”模式下执行的。

值得注意的是,不建议将Always模式部署到生产中:在开发时可以上载不完整的代码,这可能会破坏生产应用程序。

上传外部更改 

默认情况下,如果文件被某些外部进程更改,IntelliJ IDEA也会上传文件,例如VCS分支更改, SASS或LESS编译或 文件观察器。要更改此行为并跳过外部更改,请将“将更改的文件上载到默认服务器”设置 为“ 始终”,然后选中“ 跳过外部更改”复选框:

跳过外部变化

 

IntelliJ IDEA中的文件监视器 

此功能仅在Ultimate版本中受支持。

本教程的内容是什么 

本教程旨在逐步引导您使用IntelliJ IDEA中的文件观察器。

文件观察器的基础知识,特别是LESS和CoffeeScript的使用,超出了本教程的范围。

先决条件 

确保:

  • 您正在使用IntelliJ IDEA。

  • 下载并安装 Node.js。根据您的特定操作系统,建议将Node.js可执行文件的路径添加到Path环境变量中。

  • 在开始使用文件监视器之前,请确保已启用File Watchers插件。该插件与IntelliJ IDEA捆绑在一起,默认情况下处于激活状态。如果插件没有被激活,使其在对插件的页面设置/首选项对话框中的说明 管理插件

  • 建议您事先熟悉此事。请阅读使用文件监视器部分 。

  • 在本教程中,我们将使用Less和 CoffeeScript文件。因此,在开始锻炼之前,请执行一些预备步骤。

安装Node.js插件 

首先,下载并安装Node.js插件。它没有捆绑; 所以要安装它,打开 插件页面(点击图标一般设置svg主工具栏,记得吗?)并在Jetbrains存储库中查找这个插件:

py nodejs插件

要使更改生效,请重新启动IntelliJ IDEA。重新启动后,您会注意到Languages and Frameworks节点下的新页面在 Settings / Preferences 对话框中(Ctrl+Alt+S) - Node.js和NPM

安装LESS和CoffeeScript编译器 

打开设置/首选项(图标一般设置svg),然后打开页面Node.js和NPM。在此页面上,指定节点解释器(其版本自动确定),然后单击图标一般添加- 一次安装较少,另一次安装咖啡脚本。

正如您已经注意到的那样,LESS和CoffeeScript是在本地安装的,因此相应的编译器文件是在项目根目录下编写的:

py nodejs项目视图

稍后将需要这些文件。现在,是时候开始了!

配置文件观察者 

当IntelliJ IDEA检测到您正在使用文件时,它可以“观察”,它会提示设置文件监视器。

为LESS文件配置文件观察程序 

例如,当您打开以编辑LESS文件时,IntelliJ IDEA会显示通知横幅:

py nodejs较少观察者

单击添加观察者链接。IntelliJ IDEA显示以下对话框,您必须在其中指定文件观察程序类型(此处为Less),可执行文件(此处为lessc.cmd),并选择从stdout生成输出的选项:

py nodejs较少观察者新

查看此配置,您可以轻松找出文件监视器实际执行的操作:

  • 监视项目中所有Less文件的更改。

  • 编译文件扩展名为.LESS与扩展名的文件 的CSS,使用编译器lessc.cmd,在字段中指定 程序。

为CoffeeScript配置文件监视器 

接下来,打开以编辑CoffeeScript文件。IntelliJ IDEA会立即提示您为其配置文件监视器:

py nodejs coffeescript watcher

再次单击Add watcher并指定文件观察器设置,特别是CoffeeScript可执行文件:

py nodejs coffeescript watcher new

这个文件观察者做了什么?

  • 它还跟踪项目中所有CoffeeScript文件的更改。

  • 如果将扩展名为.coffee的文件编译到扩展名为.js的文件中,则使用编程字段Program.cmd编译。

  • 它使用扩展名为.coffee的文件编译成扩展文件.map,使用编程字段Program中指定的编译器coffee.cmd。

编辑文件观察者 

好的,我们在这里。打开以编辑文件my.less,并更改某些内容,例如,将变量重命名@myColor@Color,并更改其值。文件观察程序立即处理更改的源文件,并生成扩展名为css的输出文件:

py nodejs较少观察者编辑

接下来,打开以编辑CoffeeScript文件并在那里进行更改。配置的文件观察程序生成JavaScript文件和源映射文件:

py nodejs coffeescript watcher编辑

请注意,在任何一种情况下,IntelliJ IDEA都会 在源文件下的项目工具窗口中显示生成的文件。

故障排除,或发生错误? 

如果File Watcher执行的命令行工具失败,IntelliJ IDEA会在“ 运行”工具窗口中显示其输出 :

py nodejs错误

对故障排除很有帮助,不是吗?

重构简介 

在本页面:

简介 

IntelliJ IDEA提供了许多 自动重构功能,但作为开发人员,知道如何执行它们是不够的,我们需要了解这些重构是什么,什么时候我们想要应用它们,以及在使用之前要考虑的任何可能的缺点或事情他们。

正如Martin Fowler所定义的那样,重构 “......是一种用于重构现有代码体系,改变其内部结构而不改变其外部行为的规范技术”。因此,在对生产代码执行任何重构之前进行全面的测试覆盖以证明您没有无意中改变了行为之前,这一点非常重要。

本教程的目标是向IntelliJ IDEA的功能介绍那些可能不熟悉重构(尤其是自动重构)概念的人,并展示何时可能需要应用三种基本类型的重构: 重命名, 提取 和删除

重命名 

重命名 可能看起来像是一个微不足道的重构,但通过简单的查找和替换重命名通常意味着无意中更改了具有相同名称的无关项。使用IntelliJ IDEA的 重命名重构可以 最大限度地减少这些错误。

为什么重命名? 

  1. 该名称不够具有描述性

  2. 类/方法/变量名称与实际名称不匹配

  3. 引入了一些新东西,要求现有代码具有更具体的名称

代码重命名 

想象一下,当您实现某些功能或修复某些错误时,您会遇到以下代码

 

server = new Server(path, port, endpoint);
server.init();
server.run();

我们假设我们想要:

  • 重命名endpoint一个字段来描述它是什么类型的端点。

  • init()方法重命名Server为更准确地描述该方法的方法。

  • Server课程重命名为更具体的内容。

 

  1. 要重命名该endpoint字段,请将光标放在单词端点上,然后按 Shift+F6。IntelliJ IDEA将根据类名和其他方面弹出建议列表。在这种情况下,还建议使用此字段的参数名称。

    重命名该字段

    选择其中一个选项或键入您自己的选项。如果该字段有一个getter,IntelliJ IDEA会询问您是否要重命名。

    你想重命名吸气剂吗?

    您会注意到此字段的所有用法都更改为新名称,如果您已选择重命名该getter,则项目中的其他类将更新为使用新名称。有关方法重命名的更多信息,请参阅下一步。

  2. 要重命名该方法,过程是相同的:将光标置于init并按下 Shift+F6。在这里,您将获得更少的建议,因此请键入新名称:

    重命名方法

    除了重命名方法之外,还重命名方法的所有调用以及子类中所有重写/实现的方法。IntelliJ IDEA也可以重命名名称的非代码使用,如果您具有XML配置或其他引用类或方法的非Java文件,这将非常有用。如果再按Shift+F6 一次以显示重命名对话框,则可以配置 重命名的内容

    更多重命名设置

    如果重命名不仅仅适用于代码,IntelliJ IDEA将为您预览重构,因此您可以选择要进行的更改。通常在这些情况下,您可以选择不在注释中重命名事件,特别是如果原始方法名称是常用词 name

    预览重命名

    如果您不想进行某些更改,请按下 Backspace您不想更改的用法。

  3. 重命名类是类似的,但也可以通过 项目工具窗口执行。在这种情况下,因为我们发现我们想要重命名我们使用它的类,所以我们将Shift+F6 在代码中使用类名。

    重命名该课程

    当然,任何使用此类的代码也将被重命名,但您也可以选择重命名变量,继承者和代码的其他部分,以便它们与新名称对齐。同样,可以通过再次按Shift+F6下来设置这些选项。

重命名的影响 

重命名局部变量或私有方法可以在运行中相当安全地完成。例如,当您正在处理触及此代码区域的某项功能时,您可以执行此重构,因为知道影响范围有限。

重命名类或公共方法可能会影响很多文件。如果是这种情况,这种重构应至少在其自己的单独提交中,以便将更改明确地与您当时可能正在处理的任何更改或附加功能分开。

提取 

IntelliJ IDEA的提取重构使开发人员能够重新设计代码,因为当前设计变得清晰时,无论是小规模还是大规模,都不再适用于目的。

提取变量 

提取变量 是一个影响较小的变化,可以使您的 代码自我记录。它还可用于减少代码重复。

想象一下,您遇到以下代码

 

static String getUsernameFromMessage(String message) {
    return message.substring(message.indexOf("\"screen_name\":\"") + 15,
    message.indexOf("\"", message.indexOf("\"screen_name\":\"") + 15));
}

我们可以使用extract变量来提高此代码的可读性:

  • 删除重复 message.indexOf("\"screen_name\":\"") + 15)

  • 引入变量来描述每个 indexOf 调用所代表的内容

  • 删除幻数15

 

  1. 首先,让我们减少重复并引入一个描述此操作正在执行的操作的变量。将光标放在表达式中的任意位置,message.indexOf("\"screen_name\":\"") + 15) 然后按Ctrl+Alt+V。IntelliJ IDEA将为此重构建议一个上下文,并且您希望选择封装此表达式的上下文:

    选择要提取的表达式

    接下来,如果IntelliJ IDEA检测到此表达式多次出现,您可以选择替换所有出现的内容或仅替换您选择的内容。

    选择替换所有匹配项

    提取变量后,IntelliJ IDEA会根据表达式所使用的参数等内容建议可能的名称。

    选择或输入名称

    我们将使用我们自己的名字 indexOfFieldValue来描述它真正代表的含义。请注意,您可以决定是否希望此变量为最终变量。

  2. 接下来我们将为String值引入一个变量。这有两个原因:首先,记录String值代表什么,其次是因为它将帮助我们删除神奇数字。

    将光标放在某处, screen_name 然后按Ctrl+Alt+V。

    选择字符串值

    我们要给这个更有意义的名字, fieldName

    为变量命名

  3. 现在,我们将substring()使用相同的过程为另一个用作参数的表达式创建一个变量 ,我们将其称之为indexOfEndOfFieldValue

    提取变量

  4. 最后,我们可以删除幻数,因为这只是字段名称的长度。最终代码如下:

    static String getUsernameFromMessage(String message) {
        final String fieldName = "\"screen_name\":\"";
        final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
        final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
        return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
    }
    它比原始版本更长,但它更具描述性,这在像这样的代码中尤其重要,因为它不清楚每个表达式代表什么。是否适用的选择 final 取决于您的编码标准。

     

提取参数 

提取 或 添加参数 允许开发人员更改方法,以便更容易使用。您可能希望更改参数,例如通过从Object而不是对象本身传入一些值,或者您可能希望从方法体中引入一个值作为参数,以允许在更多位置使用该方法。我们将看一个后者的例子。

对于这个例子,在重构之后,我们将使用与上一个示例相同的代码,并稍微扩展它以显示同一个类中的另一个方法:

 

static String getTextFromMessage(String message) {
    final String fieldName = "\"text\":\"";
    final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
    final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
    return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
}

static String getUsernameFromMessage(String message) {
    final String fieldName = "\"screen_name\":\"";
    final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
    final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
    return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
}

我们的目标是删除我们在这两种方法中看到的重复代码。为此,我们将:

  • 更改fieldName为参数,以便我们可以将该 getUsernameFromMessage方法应用于任何字段。

  • 重命名getUsernameFromMessage为代表其更一般性质的东西

  • 删除重复的代码getTextFromMessage

  1. 将光标置于 fieldName ,然后按 Ctrl+Alt+P

    提取参数

    与其他重构一样,如果您愿意,可以为参数键入新名称。IntelliJ IDEA还预览更新的方法签名。按 Enter 批准更改。

    新方法签名有任何问题

    这个特殊问题告诉我们该方法被用作方法引用,这个更改将导致方法引用转换为lambda表达式。此消息可能表示这不是您希望执行的重构。如果是这种情况,下一个示例将显示我们可以使用Extract Method进行的方法。但是,对于这个例子,我们假设我们对引入新参数的后果感到满意,所以我们只选择 Continue。

    接下来,IntelliJ IDEA将检测现在可以通过调用新方法签名替换的任何代码。

    现在这段代码是更新方法的副本

    如果 在这种情况下选择“ 替换”,则将替换所有重复的代码,并且IntelliJ IDEA将选择适当的值以传入新参数。

  2. 此时,原始方法 getUsernameFromMessage 比它更普遍,所以我们应该重命名它。我们将光标放在名称和使用上Shift+F6,如上一节所示。

    重命名更新的方法

  3. 我们可以进一步简化代码。 内联是提取的反转,在我们这里的代码中,内联我们的临时变量可能是合适的 ,因为变量名只给我们提供了比将值直接传递给方法更多的东西。或者,假设getTextFromMessage确实是一个简单的委托getValueForField,我们可以使用内联来完全删除此方法。

    要内联,请将光标放在 getTextFromMessage 变量上,然后按 Ctrl+Alt+N

    内联不必要的方法

  4. 现在我们的最终代码如下:

    static String getValueForField(String message, String fieldName) {
        final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
        final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
        return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
    }

    我们调用原始getUsernameFromMessage方法的代码是:

    Parser::getUsernameFromMessage

    现在是

    (message) -> Parser.getValueForField(message, "\"screen_name\":\"")

    我们调用原始getTextFromMessage方法的代码是:

    String[] wordsInMessage = Parser.getTextFromMessage(message).split("\\s");

    现在是

    String[] wordsInMessage = Parser.getValueForField(message, "\"text\":\"").split("\\s");

请注意,我们应用此重构的方式会强制所有调用者传入字段名称,并且a)在代码周围传播String值的使用,并且b)可能会引入一个或多个这些String值的重复。这可能适合您的代码,特别是在处理字符串重复或不经常使用该方法时。但是,如果这不是一个权衡,你希望减少代码的重复,请参阅下一章的替代方法。

提取参数可以非常强大,因此值得阅读 更详细的帮助页面

提取方法 

帮助代码可读性的一种方法是将它放在易于理解的小部分中。 Extract方法 允许开发人员这样做,在适当的时候将代码段移动到他们自己的描述性命名方法中。

一些开发人员可能会发现自己编写的长方法执行他们想到的操作,并且当他们完成(并测试)功能时,查看代码以查看它可以被重构和简化的位置并分解这些更长的方法。或者,当开发人员在实现新功能时遇到代码时,他们意识到将一些代码提取到自己的方法中可以让他们重用现有的功能。

我们将查看与上一节相同的示例,但采用与之前略有不同的方法。

 

static String getTextFromMessage(String message) {
    final String fieldName = "\"text\":\"";
    final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
    final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
    return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
}

static String getUsernameFromMessage(String message) {
    final String fieldName = "\"screen_name\":\"";
    final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
    final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
    return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
}

正如我们之前看到的,之前的重构有一些权衡:需要将方法引用转换为lambda表达式,并且所有调用代码都需要知道所需的字段名称。我们可以选择以不同的方式删除两种方法之间的代码重复:

  • 将公共代码提取到自己的方法中。

  • 内联变量以简化剩余代码。

  1. 首先,突出显示两种方法之间常见的代码:

    突出显示重复代码的实例

    按Ctrl+Alt+M将显示“ 提取方法”对话框

    提取方法对话框

    键入新方法的名称 getValueForField,并检查参数名称和顺序。在这种情况下,我们将交换参数的顺序,因为我们更喜欢fieldName参数更接近方法的名称。这将取决于您的代码风格和团队偏好,您可能希望大声朗读名称和参数,以查看它是否有意义作为自然语言的声明。

    提取方法对话框中的最终设置

    当您按 OK时,IntelliJ IDEA将检测可以通过调用此新方法替换的代码,并将提供重构。我们要选择 是。

    重构代码重复

  2. 在这一点上,我们 getTextFromMessage 和 getUsernameFromMessage 方法都是简单的两行代码,并在这里是有意义的内联的字段名变量,方法名是足够的描述删除临时变量。按Ctrl+Alt+N开, fieldName 然后选择 重构。

    内联不必要的变量

  3. 作为最后一步,您可能希望将所有类似的方法组合在一起。根据您的设置,IntelliJ IDEA可能已将新方法直接放在您选择提取方法时所使用的方法之下,如本例中的情况。要将辅助方法放在一起,将光标放在 getValueForField 方法名称上,然后按 Ctrl+Shift+Down。这将getValueForField在现有的getUsernameFromMessage方法下放置您的新 方法。

    我们的最终代码如下:

    static String getTextFromMessage(String message) {
        return getValueForField("\"text\":\"", message);
    }
    
    static String getUsernameFromMessage(String message) {
        return getValueForField("\"screen_name\":\"", message);
    }
    
    static String getValueForField(String fieldName, String message) {
        final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
        final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
        return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
    }

    现在我们有两个非常具体的辅助方法来获取消息体和用户名,以及一个更通用的方法,可以用来从消息中获取任何字段的值。当存在经常需要的其他字段时,可以添加其他辅助方法。

请注意,Extract Parameter和Extract Method示例以相同的代码开头,但以看起来非常不同的代码结束。这不仅仅是因为我们使用了不同的重构,而是因为我们做出了不同的决定 - 在第一个示例中,我们选择完全删除重复,并将一些决策制定移动到方法的调用者。在第二个例子中,我们选择提供一个API,它隐藏了小辅助方法背后的字段名称的细节,但仍然提供了更通用的方法。我们也可以混合和匹配方法,我们选择开始的重构可能会引导我们朝着一个特定的方向,但我们可以决定我们的最终目的地。

提取的影响 

好消息是你可以很容易地撤消提取。Ctrl+Z当然,不仅要通过选择 ,而是通过 内联 创建的方法,以便代码返回原来的位置。

我们在这里提到的提取重构经常被有经验的开发人员用来随着它的发展塑造代码,并且每次触摸代码时,或多或少地使用它们并不罕见。一些未被覆盖的,如 提取界面和 提取超类,可能会对整体设计产生更广泛的影响,应该更加小心。

正在删除 

有时,当您通过几个步骤重构代码时,最终可能会得到不再使用的代码,或者理想情况下不应该使用代码。由于重构的目标是简化,您应该始终致力于删除未使用的代码 - 无论未使用的代码对应用程序的性能有何影响(未使用的代码),未使用的代码肯定会对使用和尝试的开发人员产生影响了解应用程序。

安全删除 

IntelliJ IDEA可让您 安全地删除 未使用的代码片段或整个文件,通知您删除代码是否安全,并提供在更改之前预览更改的选项。识别和处理未使用代码的最快方法是确保启用相关检查,默认情况下通常是这样:

查找未使用代码的检查

让我们继续我们之前的重构的例子。假设我们最终得到了这段代码:

 

static String getUsernameFromMessage(String message) {
    return getValueForField("\"screen_name\":\"", message);
}

static String getValueForField(String fieldName, String message) {
    final int indexOfFieldValue = message.indexOf(fieldName) + fieldName.length();
    final int indexOfEndOfFieldValue = message.indexOf("\"", indexOfFieldValue);
    return message.substring(indexOfFieldValue, indexOfEndOfFieldValue);
}

有可能在一段时间之后,当我们回到这个代码时,getUsernameFromMessage不再使用该 方法 - 可能不再需要,或者人们可以getValueForField 使用相关参数调用 。因此,假设我们对这些原因感到满意,我们可以继续使用此方法。

  1. 如果未使用的声明检查已打开,则方法名称将显示为灰色,表示未使用。

    删除未使用的方法是安全的

     

  2. 将光标放入 getUsernameFromMessage ,然后按 Alt+Enter。这将为您提供删除此方法的选项。

    删除未使用的方法

     

  3. 选择安全删除将弹出安全删除对话框,允许您搜索此方法的用法。

    安全删除对话框

    按“ 确定” 继续进行搜索。在我们的例子中,删除是完全安全的,因此删除了该方法。

  4.  

    我们的“未使用”方法可能未被标记为未使用,因为它可能会被测试覆盖。但是,如果我们仍然知道它未被使用,或者通过它检查过 Alt+F7,我们仍然可以安全地删除它。

    将光标放在方法名称上,然后按 Alt+Delete。这将像以前一样弹出安全删除对话框,这次当您按 OK时, IntelliJ IDEA会警告您此方法有用法

     

    用法发现

    按 查看用法 以查看这些是什么

    查看所有代码用法

  5. 通过双击每个用法,使用结果面板导航到用法。在我们的例子中,我们看到有一个测试调用我们想要删除的方法。

    方法用于测试

    由于此测试是为了确保我们不再需要的方法的正确性,我们也可以删除此测试。在编辑器窗口中,按下Alt+Delete 测试方法名称 ,然后 在“安全删除”对话框中单击“确定 ”。测试方法将被删除。

  6. 现在,我们将在“安全删除冲突”窗口中看到此代码不再有效。

    不再使用该方法

    由于这是我们最初想要删除的方法的唯一用法,我们可以选择“ 重新运行安全删除” 按钮。这次在“安全删除”对话框上按“ 确定”时,该 getUsernameFromMessage 方法将被删除。

删除的影响 

IntelliJ的检查可以显示未使用的代码,但是如果您的代码将打包为其他人使用的库,或者以其他方式公开公共API,则某些公共符号可能会在未处理时标记为未使用事实上,它们是由您无法控制的代码使用的。如果公共符号似乎未使用,则应检查其他系统是否以某种方式使用它们。

未使用的参数,局部变量和私有字段是删除的理想选择,因为应该很容易看到删除它们不会影响任何功能。

使用安全删除删除符号,无论它们是否未使用,都允许您在执行重构之前检查受影响的区域是否是您期望的区域,并让您控制您希望应用的更改。但是,仍然要注意警告,系统可能会使用公共符号,因此在删除这些符号时请务必小心。

结论 

IntelliJ IDEA提供了许多自动重构,所有这些都旨在让开发人员以尽可能低影响的方式重塑您的代码。目标是进行小的,渐进的更改,始终将代码保持在编译状态。重构功能的强大之处在于将较小的更改链接在一起,以便将代码转移到您想到的某个目标的方向:减少重复,删除不必要的代码,努力简化,提高可读性,或者更大程度地重新构建设计。

在处理新功能或修复错误时,可能会进行小而简单的更改,甚至是可取的,但请记住,可能需要单独应用更大的更改,以区分不应影响现有功能和功能更改的重构。

用策略模式替换条件逻辑 

当你有一个包含大量条件逻辑的方法(即if语句)时,你会遇到麻烦。众所周知,条件逻辑很难管理,并且可能导致您在单个方法中创建整个状态机。

分析示例应用程序 

这是一个简短的例子。比方说,有一种方法可以根据个人收入计算保险费用:

 

package ifs;

public class IfElseDemo {

    public double calculateInsurance(double income) {
        if (income <= 10000) {
            return income*0.365;
        } else if (income <= 30000) {
            return (income-10000)*0.2+35600;
        } else if (income <= 60000) {
            return (income-30000)*0.1+76500;
        } else {
            return (income-60000)*0.02+105600;
        }

    }
}

让我们分析这个例子。在这里,我们看到四个“收入带宽”,分为四个计算策略。一般来说,它们符合以下公式:

 

(income - adjustment) * weight + constant

我们的目标是提供单独的类来计算每个策略,并转换原始类以使其更透明。

创建并运行测试 

首先,让我们确保该课程有效。为此,使用JUnit4测试框架创建一个测试类 。

将插入符号放在类名称上,然后按Alt+Enter(或单击 图标动作intentBulb svg)。从建议的意图操作列表中,选择 Create Test:

ifelse教程创建测试

Create Test对话框中,从Testing library下拉列表中选择JUnit4 ,如果没有JUnit库,单击Fix,然后单击OK:

ifelse教程创建测试对话框

存根测试类已创建。但是,您必须提供一些有意义的代码,使用提供的快速修复(图标动作quickfixBulb svg)来创建import语句:

 

import org.junit.Test;

import static org.junit.Assert.*;


public class IfElseDemoTest {
    @Test
    public void low() {
    assertEquals(1825, insuranceFor(5000), 0.01);
    }

    @Test
    public void medium() {
    assertEquals(38600, insuranceFor(25000), 0.01);
    }

    @Test
    public void high() {
    assertEquals(78500, insuranceFor(50000), 0.01);
    }

    @Test
    public void veryHigh() {
    assertEquals(106400, insuranceFor(100_000), 0.01);
    }

    private double insuranceFor(double income) {
    return new IfElseDemo().calculateInsurance(income);
    }
}

现在让我们通过单击icons toolwindows toolWindowRun svg左侧装订线中的运行按钮来运行此测试,或者按 Ctrl+Shift+F10:

ifelse教程运行测试

所有4项测试均通过:

ifelse教程运行测试通过

提取方法 

接下来,提出原始类,将插入符号放在表达式中

 

(income-60000)*0.02+105600

并调用Extract Method Dialog对话框(Ctrl+Alt+M):

ifelse教程提取方法1

您将获得以下代码:

 

package ifs;


class IfElseDemo {

   public double calculateInsurance(double income) {
       if (income <= 10000) {
           return income*0.365;
       } else if (income <= 30000) {
           return (income-10000)*0.2+35600;
       } else if (income <= 60000) {
           return (income-30000)*0.1+76500;
       } else {
           return calculateInsuranceVeryHigh(income);
   }
}
       public double calculateInsuranceVeryHigh(double income) {
           return (income-60000)*0.02+105600;
       }
}

接下来,对60000,0.02和105600片段使用相同的Extract Method重构,并创建方法 getAdjustmentgetWeight并且 getConstant

 

package ifs;


class IfElseDemo {

    public double calculateInsurance(double income) {
        if (income <= 10000) {
            return income*0.365;
        } else if (income <= 30000) {
            return (income-10000)*0.2+35600;
        } else if (income <= 60000) {
            return (income-30000)*0.1+76500;
        } else {
            return calculateInsuranceVeryHigh(income);
    }
    public double calculateInsuranceVeryHigh(double income) {
        return (income- getAdjustment())* getWeight() + getConstant();
    }
    public int getConstant() {
        return 105600;
    }

    public double getWeight() {
        return 0.02;
    }
    public int getAdjustment() {
        return 60000;
    }
}

使用Extract Delegate重构 

接下来,选择上一章中创建的所有方法,并调用Extract委托示例 重构:

 

+

新创建的类具有名称InsuranceStrategyVeryHigh

然后从类中删除所有选定的方法IfElseDemo。因此,您将获得以下两个类:

 

package ifs;


class IfElseDemo {

    private final InsuranceStrategyVeryHigh insuranceStrategyVeryHigh = new InsuranceStrategyVeryHigh();

    public double calculateInsurance(double income) {


        if (income <= 10000) {
            return income*0.365;
        } else if (income <= 30000) {
            return (income-10000)*0.2+35600;
        } else if (income <= 60000) {
            return (income-30000)*0.1+76500;
        } else {
            return insuranceStrategyVeryHigh.calculateInsuranceVeryHigh(income);
    }

}

 

package ifs;

public class InsuranceStrategyVeryHigh {
   public InsuranceStrategyVeryHigh() {
   }

   public double calculateInsuranceVeryHigh(double income) {
       return (income - getAdjustment()) * getWeight() + getConstant();
   }

   public int getConstant() {
       return 105600;
   }

   public double getWeight() {
       return 0.02;
   }

   public int getAdjustment() {
       return 60000;
   }
}

微调 

此代码需要一些修改。首先,让我们改变班级IfElseDemo

  • 重命名(Shift+F6)域insuranceStrategyVeryHigh至 strategy

  • 使这个领域不是最终的。

  • 使用意图操作,将其拆分为声明和初始化:

    ifelse教程拆分

     

  • 将初始化向下移动到相应的if-else分支。

获取以下代码:

 

package ifs;

class IfElseDemo {

    private InsuranceStrategyVeryHigh strategy;

    public double calculateInsurance(double income) {


        if (income <= 10000) {
            return income*0.365;
        } else if (income <= 30000) {
            return (income-10000)*0.2+35600;
        } else if (income <= 60000) {
            return (income-30000)*0.1+76500;
        } else {
            strategy = new InsuranceStrategyVeryHigh();
            return strategy.calculateInsuranceVeryHigh(income);
        }

    }

}

接下来,让我们修改类InsuranceStrategyVeryHigh- 为它调用 Extract Superclass重构。

ifelse教程提取超类

注意Extract Superclass Dialog对话框中的设置:

  • 要生成的超类的名称是InsuranceStrategy

  • InsuranceStrategyVeryHigh检查类的所有方法- 这意味着它们将包含在超类中。

  • 该方法calculateInsuranceStrategyVeryHigh仍然是非抽象的; 通过选择Make Abstract复选框,所有其他方法都是抽象的。

同意将InsuranceStrategyVeryHigh类(在 IfElseDemo类中)的用法替换为超类,并获取以下 InsuranceStrategy类:

 

package ifs;

public abstract class InsuranceStrategy {
    public double calculateInsuranceVeryHigh(double income) {
        return (income - getAdjustment()) * getWeight() + getConstant();
    }

    public abstract int getConstant();

    public abstract double getWeight();

    public abstract int getAdjustment();
}

实现抽象类 

接下来,对于此抽象类,使用Implement Abstract Class意图为所有策略创建实现:

ifelse教程实现摘要

命名新的实现类InsuranceStrategyLow, InsuranceStrategyMediumInsuranceStrategyHigh

对于所有新实现return,为方法提供正确的语句 getAdjustment()getWeight()以及 getConstant()

因此,所有实现类应该看起来类似于类 InsuranceStrategyVeryHigh,但具有特定于策略的调整,权重和常量。例如:

 

package ifs;

public class InsuranceStrategyMedium extends InsuranceStrategy {
    @Override
    public int getConstant() {
        return 35600;
    }

    @Override
    public double getWeight() {
        return 0.2;
    }

    @Override
    public int getAdjustment() {
        return 10000;
    }
}

请注意,在所有新创建的实现类中,类名称都是灰色的 - 到目前为止它们尚未使用。

接下来,提出类IfElseDemo,并修改所有分支实体,以便初始化strategy字段,就像在最后一个分支中一样:

 

package ifs;

class IfElseDemo {

    private InsuranceStrategy strategy;

    public double calculateInsurance(double income) {


        if (income <= 10000) {
            strategy = new InsuranceStrategyLow();
            return strategy.calculateInsuranceVeryHigh(income);
        } else if (income <= 30000) {
            strategy = new InsuranceStrategyMedium();
            return strategy.calculateInsuranceVeryHigh(income);
        } else if (income <= 60000) {
            strategy = new InsuranceStrategyHigh();
            return strategy.calculateInsuranceVeryHigh(income);
        } else {
            strategy = new InsuranceStrategyVeryHigh();
            return strategy.calculateInsuranceVeryHigh(income);
        }

    }

}

最后,重命名方法calculateInsuranceVeryHigh:提出类 InsuranceStrategy,将插入符号放在方法名称上然后按 Shift+F6。新名称应该是calculate

快乐结束 

最后享受代码:

 

package ifs;

class IfElseDemo {

    private InsuranceStrategy strategy;

    public double calculateInsurance(double income) {
        if (income <= 10000) {
            strategy = new InsuranceStrategyLow();
            return strategy.calculate(income);
        } else if (income <= 30000) {
            strategy = new InsuranceStrategyMedium();
            return strategy.calculate(income);
        } else if (income <= 60000) {
            strategy = new InsuranceStrategyHigh();
            return strategy.calculate(income);
        } else {
            strategy = new InsuranceStrategyVeryHigh();
            return strategy.calculate(income);
        }
    }
}

接下来,让我们再次运行测试类。所有测试都应该通过 - 我们已经重构了代码,但它仍然会产生相同的结果。

TODO示例 

请考虑以下示例:为每个团队成员创建和查看TODO项目。

为TODO项目创建模式 

TODO中的页面设置 对话框中,单击图标一般添加svg在图案部分,并 创造更多的TODO模式,例如todo-Johntodo-Bob并且todo-me,新的图标,以及自定义颜色方案:

todo1

创建过滤器 

接下来,创建几个过滤器,您将用它们来显示每个开发人员的TODO项目,而不是为了您自己。为此,在过滤器部分,单击图标一般添加svg,并指定过滤器名称,例如For JohnFor BobNot for me。将这些过滤器与模式相关联:

todo2

在源代码中创建TODO项目 

现在,在源代码中,创建TODO项目:在代码行中,要添加注释,按 Ctrl+/,或Ctrl+Shift+/,键入TODO与其中一个模式匹配,然后是一些有意义的描述:

todo3

查看TODO项目 

在整个项目中生成了许多TODO项目后,在TODO工具窗口中查看它们:单击工具窗口栏上的TODO按钮以显示工具窗口。默认情况下,会显示所有遇到的TODO项目。

现在让我们显示Bob和John的TODO项目,并隐藏其他项目:点击TODO工具窗口过滤 工具栏上的过滤器图标,然后在菜单中选择Not for me:

todo5

在TODO中使用实时模板评论 

让我们探索一个先进的IntelliJ IDEA工具,为TODO项目的文本创建一个实时模板。为什么我们需要呢?例如,您希望您的团队成员创建统一的TODO项目,并自动填写用户名,然后是一些任意文本。

这就是它的完成方式。

创建TODO模式和过滤器 

打开“设置/首选项”对话框,在“编辑器”部分下,单击“ TODO”

创建模式 review。为此,请单击图标一般添加svg“ 模式”部分:

TODO创建模式

在拾色器中定义颜色 - 在这种情况下,它是粉红色。

接下来,让我们创建一个过滤器。为此,请单击图标一般添加svg“ 过滤器”部分,然后定义过滤器:

TODO创建过滤器

创建实时模板和变量 

接下来,返回在“ 设置/首选项” 对话框(Ctrl+Alt+S)中的“编辑器”部分下,单击“ 实时模板”

TODO live template1

请注意,新模板将添加到自动创建的组中user

接下来,注意底部的红色音符。它说新模板缺乏应用的背景。所以让我们点击链接定义,并允许所有可能的上下文。最后,让我们定义模板本身:在模板文本区域中,键入以下内容:

 


REVIEW[$WHO$] $TEXT$
    

我们在这里有两个未定义的变量:$WHO$$TEXT$。该变量$TEXT$ 将仅用作输入字段,而变量$WHO$应自动填充。要定义此变量,请单击“ 编辑变量 ”按钮:

TODO live template2

接下来,在“ 编辑模板变量”对话框中,选择变量的表达式 $WHO$

TODO live template3

使用REVIEW项目 

现在让我们确保它有效。回到编辑器中,创建一行注释(Ctrl+/),键入rv,然后按Tab:

TODO live template4

请注意,TODO注释旁边的右侧排水条也会添加到编辑器中。如您所见,实时模板rv已自动填充用户名,让我们只需输入一些有意义的注释:

TODO live template5

现在,当您选择仅显示REVIEW注释时,请使用过滤器。为此,请单击 过滤并选择筛选器审阅以仅显示那些具有关键字REVIEW的 TODO注释。

ij TODO live template6

使用TextMate包 

以下内容仅在安装并启用TextMate Bundles Support Plugin时有效!

这就是它的完成方式。TextMate

本教程旨在逐步引导您配置IntelliJ IDEA以使用TextMate Bundles,并使用已注册的扩展名编辑文件。

学习TextMate超出了本教程的范围。有关TextMate的信息,请参阅 产品文档

先决条件 

确保:

  • 您已经下载了要使用的软件包。例如,您可以在GitHub或 Subversion找到要安装的软件包。

  • 您正在使用IntelliJ IDEA 13.0(支持TextMate Bundles)或更高版本。

  •  

    在开始使用TextMate Bundles之前,请确保已安装并启用TextMate包支持插件 。

    py textmatebundles插件

导入包 

假设您希望IntelliJ IDEA突出显示Shell脚本文件的语法。为此,您已经下载了Shell脚本TextMate Bundle。它现在位于您的硬盘上,您只需将此软件包导入IntelliJ IDEA即可。

在Settings / Preferences 对话框(Ctrl+Alt+S)中,转到 Editor,然后单击TextMate Bundles。在 TextMate Bundles区域中,单击图标一般添加svg并找到硬盘上所需的软件包:

py textmatebundles import

单击“ 确定”以应用更改。该Shell脚本包出现在公认的包的列表:

py textmatebundles导入结果

请注意TextMate Bundles 页面下部的颜色方案映射部分 。默认情况下,IntelliJ IDEA的默认颜色方案映射到Mac Classic。要为包使用不同的颜色方案,请单击 映射表中的Mac Classic单元格,然后 从可用的方案列表中选择所需的方案。

py textmatebundles颜色

扩展冲突 

假设您导入的捆绑包与现有文件类型发生冲突。冲突立即报告:

py textmatebundles导入现有

单击“ 显示详细信息”链接将打开一个对话框,使您有机会从本机文件类型中取消注册所需的扩展名:

py textmatebundles导入扩展冲突

通过TextMate Bundles支持的节点文件现在显示新的extensions(.htm, .html),节点HTML缺少这些扩展:

py textmatebundles导入新的文件类型

+

测试 

添加TextMate包后,IntelliJ IDEA会为使用该包注册的文件类型提供语法突出显示。这是一个示例脚本,它使用我们之前克隆的Shell Script TextMate包:

py textmatebundles突出显示

 

使用Emacs作为外部编辑器 

本教程的内容是什么 

这个简短的教程旨在逐步指导您将Emacs定义为IntelliJ IDEA的外部编辑器。

Emacs的基础知识超出了本教程的范围。

先决条件 

确保:

  • 您正在使用IntelliJ IDEA 10.0或更高版本。本教程是使用IntelliJ IDEA版本2016.1创建的。

  • Emacs已下载并正确安装 在您的计算机上。

将Emacs配置为外部工具 

打开设置/首选项对话框。为此,您可以选择“ 文件”| 设置(在Windows和* nix上)或IntelliJ IDEA | 首选项 (在macOS上),或单击图标一般设置svg主工具栏上的按钮。

然后,在“ 工具”节点下,打开“ 外部工具 ”页面 。在此页面上,您必须将Emacs安装指定为当前文件的外部编辑器。这就是它的完成方式......

  1. 首先,在“ 外部工具”页面中,单击图标一般添加svg。将打开“ 创建/编辑工具”对话框。

  2. 在此对话框中,执行以下操作:
    • 输入工具名称(Emacs)和可选说明(打开Emacs)

    • 指定组的名称,Emacs将在“ 工具”菜单中显示。在此示例中,组名称为Editors。此步骤是可选的 - 如果您未指定组名,则Emacs将按原样显示在“ 工具”菜单中。

    • 清除复选框打开控制台。

    • 指定Emacs二进制文件位置。您可以手动键入,也可以单击省略号按钮,在文件系统中找到所需的二进制文件。

    • 由于您要在Emacs中打开当前文件,请将文件路径作为参数传递给程序:在“ 参数”字段中,键入$FilePath$

    • 最后,指定工作目录 - 在我们的示例中,这是 $ProjectFileDir$

    • 单击确定。

    ij emacs1

  3. 应用更改并关闭“设置/首选项”对话框。

在Emacs中打开当前文件 

现在,当您查看“ 工具”菜单时,您将看到新节点 编辑器。指向此节点将显示Emacs命令:

ij emacs2

打开文件进行编辑。接下来,在Tools菜单上,选择 Editors | Emacs - 并在Emacs中查看当前文件:

ij emacs3

分配键盘快捷键 

确保:图标一般设置svg 打开“设置/首选项”对话框,打开“ 键盘映射”页面,找到Emacs,然后在上下文菜单中选择“ 添加键盘快捷键 ”:

py emacs4

将打开“ 键盘快捷方式”对话框,您必须在其中指定要与此操作关联的快捷方式。例如,让我们使用 Ctrl+Shift+Alt+E:

py emacs5

未报告任何冲突,因此单击“确定”,然后查看操作列表和“ 工具”|中出现的新快捷方式 编辑| Emacs菜单:

py emacs6

使用IntelliJ IDEA作为Vim编辑器 

以下内容仅在安装并启用IdeaVim插件时有效!

在你开始之前 

确保:

  • 您正在使用IntelliJ IDEA 15.0.0或更高版本。如果您还没有IntelliJ IDEA,请从此页面下载。要安装IntelliJ IDEA,请按照说明操作,具体取决于您的平台。

下载并安装IdeaVim插件 

在IntelliJ IDEA主窗口的工具栏上,按Ctrl+Alt+S以打开“ 设置/首选项”对话框,然后单击“ 插件”

您会看到当前安装在您计算机上的插件列表。但是,IdeaVim插件不在其中。单击市场选项卡,在搜索字段中键入单词“vim”以缩小列表范围,然后选择IdeaVim插件:

安装vim

安装插件后,它实际上在IntelliJ IDEA重启后可用。

重启后IntelliJ IDEA的UI会发生什么? 

首先,在“ 工具”菜单上,出现一个检查命令Vim Emulator:

ij vim模拟器

“工具”菜单中的“Vim仿真器”

IntelliJ IDEA重启后,选中此检查命令。您可以通过取消选中此检查命令来禁用Vim。

其次,在“设置/首选项”对话框中,在“ 编辑器”下添加了一个附加页面 Vim Emulation。

配置快捷方式 

Vim和IntelliJ IDEA都是以键盘为中心的。使用IdeaVim插件,很可能IntelliJ IDEA的键映射与Vim键映射发生冲突。这就是IntelliJ IDEA允许您选择您喜欢哪种键盘快捷键进行特定操作的原因。这就是它的完成方式。

在Settings / Preferences 对话框(Ctrl+Alt+S)中,选择 Editor | Vim Emulation。

在“ 快捷方式”列中,选择要配置的快捷方式。接下来,在 Handler列中,单击相应的单元格,然后查看三个可能选项(Undefined,IDE,Vim)的下拉列表:

vim仿真快捷方式

如果选择IDE,则表示启用了此特定操作的IntelliJ IDEA快捷方式。当您按下时,例如,Ctrl+CIntelliJ IDEA会静默执行其操作。

如果您未定义处理程序,则在按下快捷方式时 Ctrl+C,IntelliJ IDEA会显示横幅。

要将此快捷方式重新定义为IDE快捷方式,从而接受IntelliJ IDEA的键映射,请单击IDE快捷方式链接。如果单击Vim Emulation链接,则IntelliJ IDEA将显示编辑器| “ 设置/首选项”对话框的“ Vim仿真”页面。

编辑模式 

当你启用Vim时,你会看到光标已经改变了它的形状 - 现在它是一个块,这意味着你处于Normal模式 :

ij vim正常

如果要进入插入模式,请按i,光标将变为一行:

ij vim insert

在此模式下,您可以键入新内容或更改现有代码。同样的方法,就可以进入不同的Vim模式:例如,按r为 替换模式

顺便说一下,只要您输入Vim仿真,它也会在状态栏中报告。

ps vim状态栏

要返回普通模式,请按Escape。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值