idea使用帮助文档2

使用实时模板生成自定义代码构造 

IntelliJ IDEA 为许多常见代码构造提供了大量预定义的实时模板。您还可以定义自定义模板以涵盖特定于工作流的用例。

插入实时模板 

  1. 将插入符号放在您希望模板展开的位置。

  2. 键入模板缩写并按下调用键(通常Tab默认情况下)。或者,在“ 代码”菜单上,单击“ 插入实时模板”(Ctrl+J)以打开建议列表并选择所需的模板。

  3. 如果所选模板需要用户输入,则会突出显示相应的字段。键入必要的值,然后按Enter或Tab 完成输入并移至下一个输入字段。在完成所有输入字段后,插入符号移动到构造的末尾($END$如果在模板代码中定义了标记,则移动到标记),编辑器返回到常规操作模式。

您还可以使用环绕模板包装代码片段。

使用实时模板包围一段代码 

  1. 选择要包围的代码段。

  2. 在“ 代码”菜单上,单击“ 使用实时模板环绕”(Ctrl+Alt+J)以打开建议列表并选择所需的模板。

使用实时模板在函数调用中智能完成参数 

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

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

在PHP上下文中,您可以使用“自动”实时模板,该模板为传递给函数,方法或类构造函数的参数提供完成列表。

要启用智能完成参数: 

  1. 在“ 设置/首选项”对话框(Ctrl+Alt+S)中,依次单击“ 编辑器”,“ 常规 ”和“ 智能密钥”。

  2. 选择PHP组中的启用智能功能参数完成复选框。

要为功能使用智能完成模板: 

  • 键入params关键字作为函数调用中的第一个参数。

    ps_smart_parameter_completion_step_1.png

    IntelliJ IDEA显示一个实时模板,其中参数自动使用函数声明中定义的变量名完成。

    要移至下一个参数,请按Enter或Tab。要移至上一个参数,请按Shift+Tab。

    完成列表按以下顺序包含来自本地范围的变量:具有相同类型的相同名称,在附近定义。您可以通过按Ctrl+Space 或只键入列表中没有的任何内容来切换到通常的完成模式。将自动插入具有相似名称的变量。

实现接口或抽象类的方法 

如果一个类被声明为实现某个接口或使用抽象方法扩展一个类,它必须实现这种接口或类的方法。IntelliJ IDEA为已实现的方法创建存根,具有基元类型的默认返回值,以及对象的空值。

实施所需方法 

  1. 在“ 代码”菜单上,单击“ 实现方法”(Ctrl+I)。或者,您可以右键单击类文件中的任意位置,然后单击Generate(Alt+Insert),并选择Implement methods。

  2. 选择要实施的方法。如有必要,请选中“ 复制JavaDoc”复选框以插入已实现的接口或抽象类的JavaDoc注释。

  3. 单击确定。

改变方法体 

用于实现的方法(代码模板实现的方法,体)接受来自预定义的模板变量文件头包括模板(例如${USER}${DATE}等)

例如,请考虑以下文件模板:

#if ( $RETURN_TYPE != "void" )return $DEFAULT_RETURN_VALUE;#end
// TODO ($USER, $DATE):To change the body of an implemented method, use File | Settings - Editor -  File and Code Templates.

如果实现的接口包含两个方法,则此模板将扩展为以下代码:

@Override
public void hunt() {
    // TODO (wombat, 9/21/12): To change the body of an implemented method, use File | Settings - Editor -  File and Code Templates.
}
@Override
public String sniff() {
    return null;  // TODO (wombat, 9/21/12): To change body of implemented methods use File | Settings - Editor - File and Code Templates.
}

覆盖超类的方法 

如果一个类被声明为实现某个接口或使用抽象方法扩展一个类,它必须实现这种接口或类的方法。IntelliJ IDEA为已实现的方法创建存根,具有基元类型的默认返回值,以及对象的空值。

覆盖超类的方法 

  1. 在“ 代码”菜单上,单击“ 实现方法”(Ctrl+O)。或者,您可以右键单击类文件中的任意位置,然后单击Generate(Alt+Insert),并选择Implement methods。

  2. 选择要覆盖的方法。方法列表不包括已被覆盖的方法,或者无法从当前子类访问的方法。

    如有必要,选择Copy JavaDoc复选框以为已实现的接口或抽象类插入JavaDoc注释。

    选择要覆盖的方法

    如有必要,请选中“ 复制JavaDoc”复选框,以便为重写的方法插入JavaDoc注释。

    如有必要,请选中“ 插入@Override”复选框以插入@Override注释。

  3. 单击“ 确定”并提供方法主体的源代码。

    将鼠标悬停覆盖在装订线上的图标上可查看基类的名称。单击它以打开重写的方法声明

    在排水沟中覆盖方法图标

更改方法体 

用于实现的方法(代码模板实现的方法,体)接受来自预定义的模板变量文件头包括模板(例如${USER}${DATE}等)

例如,请考虑以下文件模板:

#if ( $RETURN_TYPE != "void" )return $DEFAULT_RETURN_VALUE;#end
// TODO ($USER, $DATE):To change the body of an implemented method, use File | Settings - Editor -  File and Code Templates.

如果实现的接口包含两个方法,则此模板将扩展为以下代码:

public void breathe() {
    // TODO (wombat, 9/21/12): To change the method body, use Settings - Editor - File and Code Templates.
}

public void eat() {
    // TODO (wombat, 9/21/12): To change  the method body, use Settings - Editor - File and Code Templates.
}

环绕代码片段 

IntelliJ IDEA为周围的代码片段提供标准模板,其中包含基于源代码语言的各种构造。这包括if...else条件语句, do...whilefor循环,的组合try...catch...finally,XML标签,折叠区域,和其它结构。

用语言结构包围代码块 

  1. 选择所需的代码片段。

  2. 在代码菜单上,单击环绕(Ctrl+Alt+T)。

  3. 从列表中选择必要的环绕声。

您可以编辑环绕声明中使用的代码模板。在“ 设置/首选项” 对话框(Ctrl+Alt+S)中,转到“ 编辑器”| 文件和代码模板。

例如,您可以为try...catch条件语句配置final修饰符,名称甚至类型的异常 。

代码模板设置

 

此功能适用于以下语言(上下文):

上下文

环绕着

Java语句

  • if
  • if/else
  • while
  • do/while
  • for
  • try/catch
  • try/finally
  • try/catch/finally
  • synchronized
  • Runnable
  • {}

wrapWithStatement.png

Java表达式

  • (expr)
  • ((Type)expr)
  • !(expr instanseof Type)

wrapExpression.png

XML / HTML / JSP / JSPX标记

  • 标签

  • CDATA部分

  • <%...%>

  • 蚂蚁

 

wrapTags.png

 

JavaScript语句

  • (expr)
  • !(expr)
  • if
  • if / else
  • while
  • do / while
  • for
  • try / catch
  • try / finally
  • try / catch / finally
  • with
  • function
  • { }
  • function expression

使用if ... else构造围绕JavaScript代码片段

ActionScript语句

  • if
  • if / else
  • while
  • do / while
  • for
  • try / catch
  • try / finally
  • try / catch / finally
  • with
  • function
  • {}
  • function expression

surround_with_action_script.png

PHP语句

  • if
  • if / else
  • while
  • do / while
  • for
  • foreach
  • try / catch
  • function

surround_with_php_statements.png

自定义折叠区域注释

任何代码片段,其中Surround With适用

 

围绕任何代码块

完整配对字符 

IntelliJ IDEA可以自动添加闭合括号和其他配对元素。

用括号括起来完成代码 

  1. 在“ 设置/首选项” 对话框中(Ctrl+Alt+S)

    单击常规下的编辑器,然后智能键。将打开“ 智能钥匙”页面

  2. 选择Enter组中的Insert pair}复选框。这样可以在按下时添加闭合括号。 Enter

  3. 通过选中以下复选框配置自动插入配对元素:

    • 插入对支架
    • 插入对报价
    • 输入'</'时自动关闭标签
    • 在JSP中插入对%>
    • 在Django模板中自动插入关闭}}和%}
  4. 单击“ 确定”以应用更改。

缩进级别在“ 代码样式”设置中定义。

重构代码 

重构是在不创建新功能的情况下改进源代码的过程。重构可帮助您保持代码的稳定, 干燥和易于维护。

调用重构 

  1. 选择要重构的项目。您可以在“ 项目”工具窗口中选择文件/文件夹,也可以在编辑器中选择表达式/符号。

  2. 按下Ctrl+Shift+Alt+T打开可以选择的重构列表。

    重构这个弹出窗口

    或者,您可以使用键盘快捷键进行特定重构。

     

如果您需要撤消重构,请按Ctrl+Z。

预览重构更改 

对于某些重构,IntelliJ IDEA允许您在应用之前预览更改。

  1. 要看到潜在的变化,单击预览 在重构预览对话框。

    特定的重构对话框

     

  2. 检查将在“ 查找”工具窗口中进行的更改。您可以排除(Delete)或删除(Ctrl+X)您认为不必要的更改。

    重构预览

     

  3. 单击“ 执行重构”(N/A)以继续更改。

解决冲突 

当IntelliJ IDEA遇到重构问题时,它会打开一个对话框,其中包含冲突列表及其简要说明。

重构confilicts对话

  • 单击“ 继续”忽略该问题,然后继续在“ 查找”工具窗口中打开预览。

  • 单击“在视图中显示冲突”以在“ 查找”工具窗口中打开冲突条目并进一步处理它们。

    例如,您可以尝试通过按Delete或从单击取消排除重构的条目并返回编辑器。

    重构冲突工具窗口

配置重构设置 

  1. 在Settings / Preferences 对话框(Ctrl+Alt+S)中,选择Editor | 一般。

  2. 在“ 常规”页面上的“ 重构”部分中,调整重构选项,然后单击“ 确定”。

您还可以在编辑器中调整重构意图 用心。

IntelliJ IDEA支持的最受欢迎的重构 

安全删除

Alt+Delete

确保您不删除源代码中引用的文件。

安全删除

复制/移动

F5/F6

复制/移动元素。

移动并复制重构

提取方法

Ctrl+Alt+M

这些重构操作可帮助您减少代码重复。

提取方法

提取常数

Ctrl+Alt+C

 

提取常数

提取字段

Ctrl+Alt+F

 

提取字段

提取参数

Ctrl+Alt+P

 

提取参数

提取变量

Ctrl+Alt+V

 

提取变量

改名

Shift+F6

重命名元素。

重命名重构

排队

Ctrl+Alt+N

内联一个元素。与提取相反。

排队

改变签名

Ctrl+F6

更改方法或类的调用签名。

改变签名

更改签名 

您可以从UML类图中访问此重构 。

的更改签名重构组合可以应用于方法签名或类签名几个不同的修改。

对于一个,这种重构可以将类转换为泛型并操纵其类型参数。它会自动更正类的所有调用,实现和覆盖。

对于方法,此重构可以更改方法名称,添加,删除,重新排序和重命名参数和异常,并通过调用层次结构传播新参数和异常。

  1. 选择要更改签名的方法或类。

  2. 从上下文菜单中,选择Refactor | 更改签名(Ctrl+F6)。

  3. 在打开的对话框中,根据您要更改的签名,指定相应的选项,然后单击“ 重构”。如果要查看潜在更改的预览,请单击“ 预览”。

更改类签名示例 

我们将类型参数添加Param1, Param2 到类中MyClass

字符串和整数是分别在“ 更改类签名” 对话框中为Param1和指定的默认值Param2

您还可以为参数添加有界值,以对传递给type参数的内容施加一些限制。例如,添加Param3默认值List和有界值Collection

更改班级签名

之前

 

public class MyClass {

    public class MyOtherClass {
        MyClass myClass;
        void myMethod(MyClass myClass) {

        }
    }
}

 

 

public class MyClass<Param1, Param2, Param3 extends Collection> {

    public class MyOtherClass {

        MyClass<String, Integer> myClass;
        void myMethod(MyClass<String, Integer, List> myClass) {
        }

    }
}

 

对于 Kotlin来说,这种重构与Java相同。您可以按Ctrl+Shift+Alt+K将Java代码转换为Kotlin。

更改方法签名示例 

您可以向方法添加参数,并在“ 更改方法签名”对话框中指定不同的选项 以获得不同的结果。

您还可以向方法添加例外,它们将在调用层次结构中传播。

该 变更方法签名 重构适用于构造函数。但是,在这种情况下,名称和返回类型不能更改。

如果方法契约由@Contract注释指定,则 更改方法签名 重构也会尝试转换此类方法。但是,在某些情况下,重构可能会失败,您需要手动调整合同。

更改方法签名

添加参数 

让我们添加一个带有名称price,类型double和默认值的参数0.0

IntelliJ IDEA向方法添加参数,更新方法调用并指定默认参数值。

之前

 

public class MyClass {

    public void myMethod(int value) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;

            myClass.myMethod(1);
        }
    }
}

 

 

public class MyClass {

    public void myMethod(int i, double price) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;

            myClass.myMethod(1, 0.0);
        }
    }
}

 

使用任何变量 

让我们更新所有方法调用,并在方法调用附近查找相应类型的变量,并将其传递给方法。要实现这一点,请选中 Use Any Var选项。

因此,IntelliJ IDEA找到与新参数具有相同类型的变量 d,并在方法调用中使用它。

之前

 

public class MyClass {

    public void myMethod(int value) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}

 

 

public class MyClass {

    public void myMethod(int i, double price) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1, d);
        }
    }
}

 

重载方法 

让我们让IntelliJ IDEA保持方法调用不变,但是创建一个新的重载方法,它将使用新签名调用该方法。要实现这一点,请使用Delegate via overloading方法 选项。

请注意,新的重载方法具有旧签名。但是,它使用新签名调用该方法。 0.0 在执行重构时被指定为默认参数值。

之前

 

public class MyClass {
    public void myMethod(int value) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}

 

 

public class MyClass {
    public void myMethod(int i) {
        myMethod(i, 0.0);
    }

    public void myMethod(int i, double price) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}

 

传播参数 

让我们propagateParameters Alt+G通过调用方法将新参数传播给方法调用 myMethodCall()

因此,新参数price 通过调用方法传播到方法调用,并相应地更改方法调用。

之前

 

public class MyClass {
    public void myMethod(int value) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}

 

 

public class MyClass {
    public void myMethod(int i, double price) {

    }


    public class MyOtherClass {
        public void myMethodCall(MyClass myClass, double price) {
            double d=0.5;
            myClass.myMethod(1, price);
        }
    }
}

 

传播异常 

让我们添加一个 向类read抛出异常的方法。IOExceptionMyClass

然后让我们创建一个新类ExtendsMyClass,它将扩展 MyClass和覆盖原始read方法。

现在,如果我们回到MyClass并决定添加另一个异常,例如, TimeOutException通过这种重构,该方法read也将更新子类。

之前

 

public class MyClass {
    public void read() throws IOException{
    }
    public void myMethod(int value) {

    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}
//Let's create a new class "ExtendsMyClass".

public class ExtendsMyClass extends MyClass{
    @Override
    public void read() throws IOException{
        super.read();
    }
}

 

 

public class MyClass {
    public void read() throws IOException, TimeOutException{
    }
    public void myMethod(int value) {
    }

    public class MyOtherClass {
        public void myMethodCall(MyClass myClass) {
            double d=0.5;
            myClass.myMethod(1);
        }
    }
}

//As you see, "TimeOutException" was added.

public class ExtendsMyClass extends MyClass{
    @Override
    public void read() throws IOException, TimeOutException {
        super.read();
    }
}

将匿名转换为内在 

该 转换匿名内部 重构让你匿名类转换为命名的内部类。

  1. 将光标放在要重构的匿名类中。

  2. 在主菜单上或选择的上下文菜单中,选择Refactor | 将匿名转换为内部。

  3. 在打开的对话框中,指定新内部类的名称和将用作内部类构造函数的参数的变量。您还可以指明是否要使您的类静态。

  4. 单击“ 确定”以创建内部类。

示例 

之前

 

public class Class {
    public Interface method() {
        final int i = 0;
        return new Interface() {
            public int publicMethod() {
            return i;}
        };
    }
}

 

 

public class Class {
    public Interface method() {
        final int i = 0;
        return new MyInterfaceClass(i);
    }
}
public class MyInterfaceClass implements Interface {
    private final int
               i;
    public MyInterfaceClass(int i) {
        this.i = i;
    }
    public int publicMethod() {
        return
               i;
    }
}

转换为实例方法 

该 转换匿名内部 重构让你匿名类转换为命名的内部类。

  1. 在编辑器中,将插入符号放在要重构的方法的声明或用法上。该方法应该是 static ,其参数的类型应该是项目中的类。另请注意,您不能使用此类参数类型String

  2. 从主菜单中,选择Refactor | 转换为实例方法。

  3. 在打开的对话框中,选择转换后希望方法所属的类。方法中此类的所有用法都替换为this。

    如果需要,请更改已转换方法的可见范围。

  4. 预览并应用更改。

示例 

考虑类MyClass, ClassB 并ClassB驻留在同一个包中。

结果,MyClassClassB成为转换。

 

之前

 

public class MyClass {
     ClassA classA = new ClassA();
     ClassB classB = new ClassB();

     static public void greatMethod(ClassA classA, ClassB classB){
         System.out.println("classA = " + classA);
         System.out.println("classB = " + classB);
     }
     public void myMethod(){
         MyClass.greatMethod(classA, classB);
     }
}

 

 

public class MyClass
    ClassA classA = new ClassA();
    ClassB classB = new ClassB();

    public void myMethod(){
        classB.greatMethod(classA);
    }
}

public class ClassB {
    public void greatMethod(ClassA classA) {
        System.out.println("classA = " + classA);
        System.out.println("classB = " + this);
    }
}

封装字段 

封装字段重构允许您隐藏你的数据,并建立必要的存取。

隐藏数据并通过基于访问器方法的外部接口访问它是一个好主意。稍后您可以更改数据内部,保持与依赖于类及其可用方法的代码的完全兼容性。

  1. 在编辑器中,将插入符号放在类或所需字段或要重构的类中的任何位置。(您也可以使用“ 项目”工具窗口或“ 结构视图”进行选择。)

  2. 在主菜单或上下文菜单中,选择Refactor | 封装字段。

  3. 在打开的对话框中,检查要创建访问者的字段,指定是否要创建getter或setter方法。此外,如果要使用对相应访问器方法的调用替换所有字段实例,请选择“ 使用访问器”,即使可以访问字段也是如此。您还可以选择可见性选项。

  4. 预览并应用更改

示例 

之前

 

//File Class.java
public class Class {
    public String aString;
}

 

 

//File Class.java
public class Class {
    private String aString;
    public void setaString(String aString) {
        this.aString = aString;
    }
    public String getaString() {
        return aString;
    }
}

 

 

//File AnotherClass.java
public class AnotherClass {
    public Class aClass;
    public void method() {
        aClass.aString="string";
    }
}

 

 

//File AnotherClass.java
public class AnotherClass {
    public Class aClass;
    public void method() {
        aClass.setaString("string");
    }
}

提取重构

提取常数 

封装字段重构允许您隐藏你的数据,并建立必要的存取。

  1. 在编辑器中,选择要用常量替换的变量的表达式或声明。

  2. 按下 Ctrl+Alt+C 以引入常量或选择Refactor | 提取| 常数。

    提取常量

    从打开的列表中选择一个名称或键入您自己的名称,然后按Enter。

  3. 如果按Ctrl+Alt+C两次, 则会打开“ 提取常量”对话框。

  4. 为常量指定其他选项,例如,更改其可见性,或将常量移动到另一个类。

默认情况下,就地重构是可用的,您可以通过“ 设置/首选项”中的“ 启用就地模式”复选框来控制它 。编辑| 常规(向下滚动到“ 重构”部分)。

示例 

让我们为整个代码中出现两次的表达式“string”引入一个常量。

之前

 

public class Class {
    public void method() {
        ArrayList list = new ArrayList();
        list.add("string");
        anotherMethod("string");
    }
    private void anotherMethod(String string) {
    }
}

 

 

public class Class {
    private static final String STRING ="string";
    public void method() {
        ArrayList list = new ArrayList();
        list.add(STRING);
        anotherMethod(STRING);
    }
    private void anotherMethod(String string) {
    }
}

提取字段 

提取现场重构可以声明一个新的领域,并与选定的表达对其进行初始化。原始表达式将替换为字段的用法。

  1. 将光标放在要提取到字段中的一段代码中。

  2. 按Ctrl+Alt+F主菜单上的或,选择Refactor | 提取字段。

  3. 选择要作为字段引入的表达式。

    提取场

    如果IntelliJ IDEA在代码中检测到多个匹配项,则可以指定要替换的匹配项。

    提取字段出现次数

    提取多次出现的字段

    您可以按Ctrl+Alt+F两次以打开“ 提取字段”对话框,您可以在其中指定其他详细信息,例如可见性选项或初始化变量的选项。

    提取字段对话框

     

示例 

让我们将anotherClass.intValue();变量提取到一个字段中。因此,IntelliJ IDEA将所选变量名称更改为number并将其声明为private int number字段。

之前

 

public class Class {
    AnotherClass anotherClass;
    public void method() {
        int a = 1;

        int b = a + anotherClass.intValue();
        int c = b + anotherClass.intValue();
    }
}

 

 

public class Class {
    public AnotherClass anotherClass;
    private int number;

    public void method() {
        int a = 1;
        number = anotherClass.intValue();
        int b = a + number;
        int c = b + number;
    }
}

提取界面 

在提取现场重构可以声明一个新的领域,并与选定的表达对其进行初始化。原始表达式将替换为字段的用法。

  • 根据类的方法创建接口。

  • 重命名原始类,它实现新创建的接口。在这种情况下,IntelliJ IDEA会更改原始类的所有用法,以尽可能使用接口。

此外,在初始类中声明的静态final字段可以移动到接口。因此,将创建包含特定方法和字段的接口。从而,指定的类方法成为相应接口方法的实现。

示例 

这里我们有一个类,并执行 Extract Interface 重构以根据类的方法创建一个接口。

之前

 

// File AClass.java
class AClass {
    public static final double CONSTANT=3.14;
    public void publicMethod() {//some code here}
    public void secretMethod() {//some code here}
}

 

 

// File AClass.java
class AClass implements AnInterface {
    public void publicMethod() {//some code here}
    public void secretMethod() {//some code here}
}
// File AnInterface.java
public interface AnInterface {
    double CONSTANT=3.14;
    void publicMethod();
}

 

Extract Interface 重构的另一个例子 ,当选择 重命名原始类和使用可能的接口 选项时。

之前

 

public class FormerAClass implements AClass {
    public void publicMethod() {//some code here}
    public void secretMethod() {//some code here}
}

 

 

public interface AClass {
    double CONSTANT=3.14;
    void publicMethod();
}

 

您可以从已实现另一个接口的类中提取接口。让我们从实现的类中提取接口AnInterface。根据我们是否需要 AnotherInterface (提取的接口)扩展AnInterface (现有的)或我们希望源 AClass 来实现它们,我们将获得以下代码:

提取的接口扩展了现有的接口:

class AClass implements AnotherInterface {
    public void publicMethod() {
        //some code here
    }
    public void secretMethod() {
        //some code here
    }
}

提取的界面:

public interface AnotherInterface extends AnInterface {
    }

源类实现两个接口。

来源类:

class AClass implements AnInterface, AnotherInterface {
    public void publicMethod() {
        //some code here
    }
    public void secretMethod() {
        //some code here
    }
}

提取的界面:

public interface AnotherInterface {
}

提取界面 

  1. 在“ 项目”视图,“ 结构”视图中选择一个类,或将插入符放在编辑器中的类中的任何位置。

  2. 在主菜单上或从选择的上下文菜单中,选择 Refactor | 提取| 界面。将出现“ 提取接口”对话框。

  3. 要提取新接口,请选择“ 提取接口” 选项并指定新接口的名称。 
    要重命名原始类并使其成为新创建的接口的实现,请选择“ 重命名原始类并使用可能的接口 选项”并指定原始类的新名称。IntelliJ IDEA将所有原始类用法改为仅在仍然需要的情况下实现的用法。

  4. 指定新接口所在的包。

  5. 在“要添加到表单的成员 ”界面中,选择要在界面中列出的类成员 。该列表显示了该类的所有方法,以及最终的静态字段(常量)。

  6. 在 JavaDoc 区域中,选择要在JavaDoc上应用的操作。

    • 要将其保留在原位,请选择“ 原样” 选项。

    • 要将其复制到解压缩的界面,请选择“ 复制” 选项。

    • 要将其移至提取的界面,请选择“ 移动” 选项。

  7. 单击“ 重构” 继续。

  8. 准备好后 单击“ 重构”。如果IntelliJ IDEA 在“ 查找”工具窗口中显示“ 重构预览 ” ,请查看建议的更改。要提取接口并应用建议的更改,请单击“ 执行重构”。

提取方法 

提取现场重构可以声明一个新的领域,并与选定的表达对其进行初始化。原始表达式将替换为字段的用法。

提取方法时,需要检查变量。如果有一个输出变量,则将其用作提取方法的返回值。如果存在多个输出变量,则可能不会应用“ 提取方法”重构,并显示错误消息。

此外,在初始类中声明的静态final字段可以移动到接口。因此,将创建包含特定方法和字段的接口。从而,指定的类方法成为相应接口方法的实现。 在这种情况下,提取方法工作。例如,您可以引入包含所有输出值的特殊数据类。

Extract Method重构具有以下限制:

  • 重构不适用于自动模式下的多个输出值。在应用重构之前,您必须更改代码。

  • 重构不适用于有条件地从包含方法返回的代码片段,并且不会放在它的末尾。

提取方法: 

  1. 选择要提取到方法的代码片段。

  2. 按Ctrl+Alt+M主菜单上的或,选择 Refactor | 提取| 方法。

  3. 在打开的对话框中,配置方法选项,例如可见性,参数等。如果需要,您还可以更改方法的名称。

    提取方法对话框

    单击确定。

     

  4. 如果IntelliJ IDEA检测到可以通过调用提取方法替换的重复代码片段,它将提供您预览代码,并排比较并根据需要进行更改。您还可以右键单击重复的代码片段,然后选择“ 排除”以从重构中删除此类代码。

    重复分析

    准备好后,单击“ 执行重构”以完成重构。

     

    请注意,如果它只是一个副本,IntelliJ IDEA将静默替换它。

    最后,如果IntelliJ IDEA检测到仅部分重复的代码,则建议您提取参数以继续重构。

    部分重复

     

示例 

让我们将a+b表达式提取到一个方法(Kotlin的函数)中,并替换重复项。

之前

 

public void method() {
    int a=1;
    int b=2;
    int c=a+b;
    int d=a+c;
}

 

 

public void method() {
    int a=1;
    int b=2;
    int c=add(a,b);
    int d=add(a,c);
}
...
private int add(int a, int b) {
    return a+b;
}

提取超类 

提取超让你无论是创建基于退出类的超类或因此它成为新创建的超类的实现,你可以重命名原始类。在这种情况下,IntelliJ IDEA会更改所有原始类用法,以尽可能使用超类。

原始类中的字段和方法可以移动到超类。同样对于方法,您只能传递方法声明,而不能传递在超类中将方法声明为抽象的实现。因此,您将拥有从超类继承的超类和原始类。

  1. 在编辑器中打开该类,然后从主菜单中选择 Refactor | 提取| 超类。

  2. 在打开的对话框中,为要包含的类,位置和类成员指定一个名称,以形成超类。选择Make abstract复选框以将方法实现保留在当前类中,并在提取的超类中将其声明为abstract。单击“ 重构”。

示例 

之前

 

// File Class.java
public class Class {
    public int varInt;
    private double varDouble;
    public static final int CONSTANT = 0;
    public void publicMethod() {
        ...
    }
    public void hiddenMethod() {
        ...
    }
    public void setVarDouble(double var) {
        this.varDouble = var;
    }
    public double getVarDouble() {
        return
                  varDouble;
    }
}

 

 

// File Class.java
public class Class extends SuperClass {
    public int varInt;
    public void publicMethod() {
    ...
    }
    public void hiddenMethod() {
    ...
    }
}

// NEW file SuperClass.java
public abstract class SuperClass {
    private double varDouble;
    public static final int CONSTANT = 0;
    public abstract void publicMethod();
    public void setVarDouble(double var) {
        this.varDouble = var;
    }
    public double getVarDouble() {
        return varDouble;
    }
}

提取变量 

如果您遇到一个难以理解的表达式或者在整个代码中的多个位置都存在重复,则 Extract Variable 重构可以帮助您处理将此类表达式或其部分的结果放入一个不太复杂的单独变量的问题而且更容易理解。此外,它减少了代码重复。

从Java 1.8及更高版本开始,IntelliJ IDEA还允许您 提取功能类型变量

  1. 在编辑器中,选择要提取的表达式或其部分。您也可以将光标放在表达式中,在这种情况下,IntelliJ IDEA会为您提供潜在代码选择的列表。

  2. 按Ctrl+Alt+V主菜单上的或,选择 Refactor | 提取| 提取变量。

  3. 选择弹出窗口中建议的名称或键入您自己的名称,然后按Enter。

    提取物变种

    如果IntelliJ IDEA找到多个匹配项,则可以指定是否要为所有这些变量提取此变量。

    您还可以声明要提取的变量final

    如果要将现有变量重新分配给新变量,请按Ctrl+Alt+V。如果您有多个现有变量,IntelliJ IDEA会显示一个列表供您选择。

    您可以按Shift+Tab来更改变量的类型。

    改变var的类型

如果未在“ 设置/首选项”中选择“ 启用就地模式”选项 编辑器|常规对话框(重构部分),IntelliJ IDEA打开此重构的“ 提取变量”对话框。

提取var对话框

示例 

让我们提取在anotherClass.inValue()整个代码中出现两次的变量并为其命名number

之前

 

public void method() {
    int a = 1;
...
    int b = a + anotherClass.intValue();
    int c = b + anotherClass.intValue();
}

 

 

public void method() {
    int a = 1;
...
    int number = anotherClass.intValue();
    int b = a + number;
    int c = b + number;
}

 

提取功能变量 

这种重构为Java 1.8及更高版本创建了一个函数表达式,为旧版Java创建了一个匿名类。

  1. 在此示例中,选择代码片段,即println方法的参数。

    参数println

     

  2. 在主菜单中,选择Refactor | 提取| 功能变量。
    IntelliJ IDEA将打开“ 提取功能变量”对话框。

    extrct funtional var

     

  3. 当所选代码依赖于实例字段时,如示例中所示, 将显示Pass字段as params复选框,您可以在字段位置传递参数。

    extrct funtional var参数

    但是,例如,如果您选择的代码片段取决于任何局部变量或参数

    样本字符串

    相应的条目将出现在列表中。

    局部变量和参数

    取消选择对话框中的某个参数时,将使用相应的本地值。

    当param取消选择时

    配置选项并单击“ 确定”。

     

  4. 从弹出窗口中选择适用的功能界面。

    功能界面

     

  5. 如果需要,如果您不想使用列表中建议的名称,请更改提取变量的名称。

    更改变量名称

     

  6. IntelliJ IDEA创建了可以进一步使用的lambda。

    组合功能

     

示例 

之前

 

import java.util.List;

public class PrintAction implements Runnable {
    private List<String> data;

    public PrintAction(List<String> data) {
        this.data = data;
    }

    public void run() {
        System.out.println("Data: " + data.toString());
    }
}

 

 

import java.util.List;
import java.util.function.Function;

public class PrintAction implements Runnable {
    private List<String> data;

    public PrintAction(List<String> data) {
        this.data = data;
    }

    public void run() {
        Function<List<String>, String> presenter = (p) -> "Data: " + p.toString();
        System.out.println(presenter.apply(data));
    }
}

提取参数 

“ 提取参数”重构允许您向方法提取新参数。

您还可以使用Extract Functional Parameter重构。在这种情况下,IntelliJ IDEA分析所选代码,找出提取片段的方法签名,找到具有此方法签名的所有功能接口,并使用基于所选接口的匿名类包装代码片段并使用此匿名类作为参数。

  1. 在编辑器中,将光标放在要作为参数引入的表达式中。

  2. 按Ctrl+Alt+P主菜单上的或,选择Refactor | 提取| 参数。如果要提取功能参数,请按Ctrl+Shift+Alt+P主菜单上的或,选择重构| 提取| 功能参数。

  3. 指定参数的名称,在“ 提取参数” 弹出窗口中选择必要的选项。例如,如果您不想更改现有方法调用,请选中“ 通过重载方法委派”复选框。

  4. 如果需要,请按Shift+Tab更改新参数的类型。(如果在此步骤中您想要返回编辑参数名称,请按Tab。)

提取参数示例 

提取新参数时,您可以在现有方法中引入参数,也可以使用 Delegate via overloading方法选项保存原始方法并使用参数定义新方法。

让我们来替换字符串值"Hello, World!"的方法generateText ()与新的参数text。该值"Hello, World!"将传递给更新的方法调用中的方法generateText("Hello, World!")

  • Java的
  • 科特林

之前

 

public class HelloWorldPrinter {
    public static void print() {
        System.out.println(generateText());
    }
    private static String generateText() {
        return "Hello, World!".toUpperCase();
    }
}

 

 

public class HelloWorldPrinter {
    public static void print() {
        System.out.println(generateText("Hello, World!"));
    }
    private static String generateText(String text) {
        return text.toUpperCase();
    }
}

 

现在让我们通过重载方法使用Delegate。在这种情况下,将创建一个新的重载方法,并在此方法的定义中提取新参数(第二个generateText()方法)。现有generateText()方法的签名 不会更改。但是,该方法本身已被修改。现在,它调用new generateText()方法并"Hello, World!"在此调用中将值传递给它。请注意,generateText()(在方法中print())的现有调用不会更改。

之前

 

public class HelloWorldPrinter {
public static void print() {
System.out.println(generateText());
}
private static String generateText() {
return "Hello, World!".toUpperCase();
}
}

 

 

public class HelloWorldPrinter {
public static void print() {
System.out.println(generateText());
}
private static String generateText() {
return generateText("Hello, World!");
}
private static String generateText(String text) {
return text.toUpperCase();
}
}

 

功能参数示例 

让我们在System.out.println(s); 内部进行重构Hello.printHello()

IntelliJ IDEA使用适当的方法签名((String) -> void)查找所有功能接口,并建议您选择其中一个。(在此示例中,Person选择了接口。)

因此,选定的fragment(System.out.println(s);)将使用基于接口的匿名类进行包装Person。此匿名类作为参数传递给printHello() 内部调用printText()

Person 被添加为参数,printHello()并且最初选择的代码片段被替换为对interface(sayHello())方法的调用。

之前

 

@FunctionalInterface
public interface Person {
    public void sayHello (String s);
}

public class Hello {
    private void printHello () {
        String s="Hello";
        System.out.println(s);
    }
    private void printText () {
        printHello();
    }
}

 

 

@FunctionalInterface
public interface Person {
    public void sayHello (String s);
}

public class Hello {
    private void printHello(Person person) {
        String s = "Hello";
        person.sayHello(s);
    }
    private void printText () {
        printHello(new Person() {
            public void sayHello(String s) {
                System.out.println(s);
            }
        });
    }
}

 

Extract Parameter重构的特别注意事项 

  • 如果希望在方法声明中将字段作为新参数提供,则在方法调用中,此字段将显示为类实例的字段。

  • 如果类成员不可访问(例如,在上面的示例中该字段是私有的),它将被插入到方法调用中,但会突出显示为使该文件无法编译的错误。

  • 如果您使用Extract Parameter使用getter重构字段,系统将提示您使用扩展对话框。该对话框有一个选项组将表达式中使用的字段替换为其getter:
    • 不要替换:调用getter时,不会替换任何字段。

    • 替换使用上下文中不可访问的字段:只有对使用上下文无法直接访问的字段才会被调用getter替换。

    • 替换所有字段:所有字段将替换为对getter的调用。

  • 对局部变量应用重构将调用 Extract Parameter 对话框以及其他复选框:
    • 替换所有出现的次数(<number_of_occurrences>出现次数):如果启用,则所有出现的所选变量将替换为参数,并且 启用“ 删除变量定义”复选框。否则,只有选定的变量用法将替换为参数。

    • 删除变量定义:如果启用,将删除变量定义。

    • 使用变量初始值设定项初始化参数:如果启用,则变量初始值设定项将用于初始化方法调用中的参数。

副作用 

使用 Extract参数 重构如果应用于作为实际方法参数的类实例或表达式,则会产生意外的副作用。例如,在这种代码的情况下:

class AClass {
    int field;
    int method() {
        return field;
    }
}

class Usage {
    void method(List list) {
        int sum = 0;
        for(Iterator it = list.iterator(); it.hasNext(); ) {
            sum += ((AClass) it.next()).method();
        }
    }
}

重构后的代码应用于字段field

class AClass {
    int field;
    int method(int newfield) {
        return newfield;
    }
}

class Usage {
    void method(List list) {
        int sum = 0;
        for(Iterator it = list.iterator; it.hasNext(); ) {
            sum += ((AClass) it.next()).method(((AClass) it.next()).field);
        }
    }
}

迭代器值增加了两倍,实际上并不是您期望的行为。

但是,IntelliJ IDEA可以成功使用临时变量并解决增量/减量/赋值操作和新关键字用法等情况。例如:

public int myMethod(List list) {
    return list.size();
}

public void anotherMethod() {
    myMethod(new ArrayList());
}

重构后的相同代码如下所示:

public int myMethod(List list, int newPar) {
    return list.size();
}
public void anotherMethod() {
    final ArrayList list = new ArrayList();
    myMethod(list, list.size());
}

list创建了新变量,并使用此变量提供了用于方法调用的所有参数。

提取到类重构 

IntelliJ IDEA允许您使用将字段,方法和参数提取到新类中的重构。当一个类变得太大而“做太多事情”时,这些重构很有用。在这种情况下,将类拆分为更小,更具凝聚力的类可能是个好主意。

  1. 选择要提取到类中的代码片段。

  2. 根据要提取的内容,从主菜单中选择以下选项之一:
    • 重构| 提取| 代表
    • 重构| 提取| 方法对象
    • 重构| 提取| 参数对象
  3. 在打开的对话框中,指定新类,方法和参数选项的名称。

  4. 预览更改并单击“ 确定”。

提取委托示例 

该提取物委托重构,您可以提取一些字段和一类的方法到一个单独的,新创建的类。

之前

 

public class Foo {
    private String b;
    public String getInfo() {
        return ("(" + b + ")");
    }
...
}

public class Bar {
    Foo foo;
    String t2 = foo.getInfo();
...
}

 

 

public class Foo {
    private final Info info = new Info();
    public String getInfo() {
        return info.getInfo();
    }
...
}

public class Info {
    private String b;
    public Info() {}
    public String getInfo() {
        return ("(" + b + ")");
    }
}

public class Bar {
    Foo foo;
    String t2 = foo.getInfo();
...
}

 

提取方法对象示例 

该 提取方法对象 重构方法移动到一个新的类,将所有的局部变量的领域,让您分解方法到同一物体上的其他方法。它是Extract方法的替代方法,可以在提取的方法中具有多个返回值时使用。

如果所选方法代码块包含应在其他位置单独访问的局部变量,则无法将方法对象提取到匿名类中。在这种情况下,方法对象可以被提取到内部类中,其中包含所需的getter。

之前

 

class Account {
int gamma (int val1, ...) {
//some computations
return c-2*a;
}
}

 

 

class Account {
    int gamma (int val1, ...) {
        Calculations calculations = new Calculations(val1, ...).invoke();
        int c = calculations.getC();
        int a = calculations.getA();
        return c-2*a;
    }
    private class Calculations {
        private int val1;
        ...
        private int a;
        private int c;
        public Calculations(int val1, ...) {
            this.val1 = val1;
            ...
        }
        public int getA() {return a;}
        public int getC() {return c;}
        public Calculations invoke() {
            ...//computations
               return this;
        }
    }
}

 

提取参数对象示例 

该提取参数对象重构,您可以选择一组参数的方法,以及创建一个包装类的参数,或使用现有的兼容的包装类。对所选方法的所有调用都将适当地包装其参数,并且包装参数的所有用法将被新创建的参数类上的相应调用替换。

之前

 

public class A {
    private void drawEdge(Graphics g, float edgeWidth,
        int x1, int x2, int y1, int y2) {
        final Graphics2D g2d = (Graphics2D) g;
        g2d.setStroke(new BasicStroke(edgeWidth));
        g.drawLine(x1, y1, x2, y2);
    }
}

 

 

public class A {
    private void drawEdge(Edge edge, Graphics g) {
        final Graphics2D g2d = (Graphics2D) g;
        g2d.setStroke(new BasicStroke(edge.getEdgeWidth()));
        g.drawLine(edge.getX1(), edge.getY1(), edge.getX2(), edge.getY2());
    }
}

public class Edge {
    private final float edgeWidth;
    private final int x1;
    ...
    public Edge(float edgeWidth, int x1, int x2, int y1, int y2) {
        this.edgeWidth = edgeWidth;
        this.x1 = x1;
        ...
    }
    public float getEdgeWidth() {
        return edgeWidth;
    }
    public int getX1() {
        return x1;
    }
    ...
}

查找和替换代码重复 

“ 查找和替换代码重复项”操作允许您查找与所选方法或常量字段类似的代码重复,并将其替换为对原始方法或常量的调用。它还允许您指定搜索范围。

  1. 将光标定位在要搜索其重复项的方法或常量字段中。

  2. 从主菜单或上下文菜单中,选择Refactor | 查找和替换代码重复项。

  3. 在打开的对话框中,选择IntelliJ IDEA查找代码重复的范围。

  4. 对于每个找到的代码副本,IntelliJ IDEA将提示您确认替换。

示例 

之前

 

public void method() {
    int a = 1;
    int b = 2;
    int c = a+b;
    int d = b+c;
}
...
private int add(int a, int b) {
    return a+b;
}

 

 

public void method() {
    int a = 1;
    int b = 2;
    int c = add(a,b);
    int d = add(b,c);
}
...
private int add(int a, int b) {
    return a+b;
}

通用重构 

“ 查找和替换代码重复项”操作允许您查找与所选方法或常量字段类似的代码重复,并将其替换为对原始方法或常量的调用。它还允许您指定搜索范围。

  1. 将光标定位在要搜索其重复项的方法或常量字段中。 “项目”或“ 结构”视图,或将光标放在编辑器中的类或方法名称上。如果要将泛型应用于单个代码片段,请在编辑器中选择一个。

  2. 从主菜单或上下文菜单中,选择Refactor | 查找和替换代码重复项。

  3. 在打开的对话框中,选择IntelliJ IDEA查找代码重复的范围。 重构选项

    生成代码

     

  4. 对于每个找到的代码副本,IntelliJ IDEA将提示您确认替换。 预览并应用更改

示例 

IntelliJ IDEA尝试生成代码,从Java的角度来看尽可能正确。换句话说,每个上下文都引入了一些类型限制,并且重构产生了<String>与现有上下文不矛盾的最佳类型(在我们的例子中)。

之前

 

public void method() {
    List list = new LinkedList();
    list.add("string");
}

 

 

public void method() {
    List<String> list = new LinkedList<String>();
    list.add("string");
}

内联 

内嵌重构让你扭转提取重构的方法,构造函数,参数,超,匿名类和变量。

  1. 将光标放在要内联的代码片段中。

  2. 按Ctrl+Alt+N。或者,单击“ 重构”| 内联。

  3. 在“ 内联”对话框中,指定内联选项。

  4. 预览并应用更改。

示例 

内联变量 

内联变量 重构用其初始化程序替换冗余变量使用。

必须在声明时初始化变量。如果在代码中的某处修改了初始值,则只会修改修改前的出现次数。

之前

 

public void method() {
    int number = anotherClass.intValue();
    int b = a + number;
}

 

 

public void method() {
    int b = a + anotherClass.intValue();
}

 

 

public void method() {
    AnotherClass.InnerClass aClass = anotherClass.innerClass;
    int a = aClass.i;
}

 

 

public void method() {
    int a = anotherClass.innerClass.i;
}

 

内联方法 

内联方法导致将方法的主体放入其调用者的主体中。

之前

 

public void method() {
    int c=add(a,b);
    int d=add(a,c);
}

private int add(int a, int b) {
    return a+b;
}

 

 

public void method() {
    int c= a + b;
    int d= a + c;
}

 

 

public ArrayList method() {
    String[] strings = {"a","b","c"};
    ArrayList list=add(strings);
    return list;
}

private ArrayList add(String[] strings) {
    ArrayList list = new ArrayList();
    for (int i=0; i< strings.length; i++)
        {list.add(strings[i]);}
    return list;
}

 

 

public ArrayList method() {
    String[] strings = {"a","ab","abc"};
    ArrayList list1 = new ArrayList();
    for (int i=0; i< strings.length; i++)
        {list.add(strings[i]);}
    ArrayList list = list1;
    return list;
}

 

内联构造函数 

内联构造函数允许压缩构造函数链,如果其中一个是另一个构造函数的特殊情况。

之前

 

public class Class {
    public int varInt;
    public Class() {
        this(0);
    }

    public Class(int i) {
        varInt=i;
    }

    public void method() {
        Class aClass=new Class();
        ...
    }
}

 

 

public class Class {
    public int varInt;
    public Class(int i) {
        varInt=i;
    }
    public void method() {
        Class aClass=new Class(0);
        ...
    }
}

 

内联超类 

内联超类重构推父类的方法分成在那里它们被使用的类,并除去超类的结果。

之前

 

public class Bar {
    ...
    int calculations1() { ... }
    int calculations2() { ... }
}

class Foo extends Bar {
    int someMethod() {
        ...
        if (something > calculations1()) {
            ...
            return calculations2();
        }
        ...
    }
}

 

 

class Foo {
    ...
    int someMethod() {
        ...
        if (something > calculations1()) {
            ...
            return calculations2();
        }
        ...
    }
    int calculations1() {...}
    int calculations2() {...}
}

 

内联到匿名类 

内联到匿名类重构允许用其内容替换冗余类。
从Java 8开始,内联的匿名类可以自动转换为lambda。

之前

 

import java.util.*;
public class Main {
    public class MyComparator implements Comparator<String> {
        @Override
        public int compare(String s1, String s2) {
            return 0;
        }
    }

    void sort(List<String> scores) {
        scores.sort(new MyComparator());
    }
}

 

 

import java.util.*;

public class Main {

    void sort(List<String> scores) {
        scores.sort((s1, s2) -> 0);
    }
}

反转布尔 

内嵌重构让你扭转提取重构的方法,构造函数,参数,超,匿名类和变量。

  1. 将插入符号放在要重构的方法或变量的名称上。

  2. 在主菜单或上下文菜单中,选择Refactor | 反转布尔值。

  3. 在打开的对话框中,指定反转方法或变量的名称。

  4. 预览并应用更改

示例 

之前

 

private double a;
...
public boolean method() {
    if (a > 15 && a < 100) {
        a = 5;
        return true;
    }
    return false;
}

 

 

private double a;
...
public boolean method() {
    if (a > 15 && a < 100) {
        a = 5;
        return false;
    }
    return true;
}

 

 

boolean b = true;
...
public double method() {
    ...
    b = false;
    ...
}

 

 

boolean b = false;
...
public double method() {
    ...
    b = true;
    ...
}

制作静态 

制作静态重构转换内部类或实例的方法来静态的。

对于,此重构还会自动更正代码中对类的所有引用。

对于方法,此重构还会自动更正方法的所有调用,实现和覆盖。

  1. 选择要重构的方法或类。

  2. 在主菜单或上下文菜单中,选择Refactor | 制作静态。

  3. 在打开的对话框中,指定重构选项。
    • 对于,如果类引用任何外部类字段,IntelliJ IDEA建议将外部类作为参数传递给内部类构造函数。

    • 对于方法,如果方法引用任何包含的类字段,则可以将整个引用的对象作为参数传递给方法(将对象添加为带名称的参数)或将引用的字段/变量作为参数传递给方法(添加字段参数)。

      如果方法不包含对字段或实例变量的任何引用,则可以指定是否要使用类引用替换实例限定符。

  4. 预览并应用您的更改

制作方法静态示例 

之前

 

class ConnectionPool {
    public int i;
    public int j;
    public void getConnection() {
        ...
    }
}

 

 

class ConnectionPool {
    public int i;
    public int j;
    public static void getConnection(ConnectionPool connectionPool) {
        ...
    }
}

 

 

class ConnectionPool {
    public int i;
    public int j;
    public void getConnection() {
        ...
    }
}

 

 

class ConnectionPool {
    public int i;
    public int j;
    public static void getConnection(int i, int j) {
        ...
    }
}

 

在调用层次结构中,如果方法调用者不包含对实例成员的任何其他引用,则IntelliJ IDEA建议您也将这些调用者设置为静态。在此示例中,执行重构baz(int i)。选择所有调用方法也可以制作静态方法。相应的对话框允许您选择要使其成为静态的调用方法。

之前

 

class CallHierarchySample {
     private void foo(int i) { bar(i);}
     private void bar(int i) { baz(i);}
     private void baz(int i) { }
}

 

 

class CallHierarchySample {
    private static void foo(int i) { bar(i);}
    private static void bar(int i) { baz(i);}
    private static void baz(int i) { }
}

迁移 

通过迁移重构,您可以轻松地在项目中使用的旧包和类以及新项之间进行切换。IntelliJ IDEA附带默认迁移映射。

  1. 在主菜单上,选择Refactor | 迁移。

  2. 在打开的对话框中,从下拉列表中选择所需的迁移映射,或单击“ 新建”以创建新映射。

  3. 指定地图的名称和可选的地图描述。

  4. 单击图标一般添加(添加)图标以创建新的迁移说明。

  5. 在打开的对话框中,指定以下选项:
    • 选择是否要迁移包或类。

    • 指定包或类的旧名称和新名称。

    单击“ 确定”以应用更改并关闭对话框。

  6. 根据需要创建或编辑任意数量的迁移说明,然后单击“ 确定”。

  7. 单击“运行”以使用所选映射开始迁移。

移动和复制重构 

通过迁移重构,您可以轻松地在项目中使用的旧包和类以及新项之间进行切换。IntelliJ IDEA附带默认迁移映射。

执行复制重构 

  1. 选择要重构的标识符(例如,编辑器中的类或“ 项目”工具窗口中的文件)。

  2. 选择Refactor | 复制(F5)

  3. 在“ 复制”窗口中,指定副本的名称和位置,然后单击“ 确定”。

该移动重构使您可以在项目的源根,类成员之间移动包和类与其他类和内部类上层级。 
例如, 如果在另一个类中使用的方法 或字段比在其自己的类中使用更多,则可以对方法或 字段执行移动重构 。

执行移动重构 

  1. 选择要重构的标识符。

  2. 选择Refactor | 移动(或按F6)。

  3. 在打开的对话框中,根据您为重构选择的项目打开,指定相应的选项,然后单击“ 重构”(包中的“ 确定 ”)。您还可以单击预览(如果可用)以预览潜在的更改。

  4. 指定目标目录的路径,文件名和包名称。

当您对包执行移动重构时,您需要指定将包及其内容移动到哪里(到另一个包,源根或其他目录)。

将静态方法移动到另一个类 

  1. 在编辑器中打开您的课程,将插入符号放在要移动的静态方法上,然后按F6。

  2. 在“ 移动成员”对话框中,指定以下选项:

    • 在 要移动到另一个类(仅限静态)字段的成员中,选择要移动到另一个类的方法旁边的复选框。该列表显示当前类中检测到的所有静态方法。

    • 在“ 将成员移动到类”字段中,键入要在方法列表中移动所选成员的类的完全限定名称。您可以单击该 省略图标以选择或搜索现有类。

     

    移动成员对话框

     

  3. 单击“ 重构”以继续,或单击“ 预览” 以在实际重构之前检查结果。

将实例方法移动到另一个类 

如果此方法在项目中具有类型参数,则可以将实例(非静态)方法移动到其他类。在任何其他情况下,您需要首先使用此方法static

关于移动没有类型参数的实例方法的消息

  1. 在编辑器中,将插入符号放在实例方法上并按F6 (重构|移动)。

  2. 在打开的“ 移动实例方法”对话框中,指定以下内容:

    • 在“ 选择实例表达式”列表中,选择要将实例方法移动到的目标类。潜在移动目标列表包括当前类中的方法参数类和字段类。

    • 在“ 可见性”区域中,选择目标方法的首选可见性修改器。

    • 在“ 参数名称”中,将“参数引用”替换为类<class_name>字段,键入所需的参数名称。执行重构时,将为要移动的方法添加参数,该参数将替换当前类的所有参数引用。

     

    移动实例方法对话框

     

  3. 单击“ 重构”以继续,或单击“ 预览” 以在实际重构之前检查结果。

实例方法示例 

让我们将getName实例方法从Test 类移到Car类。

之前

 

import java.lang.reflect.InvocationTargetException;

public class Test {

    public static void main(String[] args) throws Exception {
        Car c= new Car();
        System.out.println(c.getName(new Test()));
    }
}

class Car {
    String name = "Default Car";

    Car() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
    }

    String getName(Test anotherObject){
        System.out.print(anotherObject.toString());
        return this.name;
    }
}

 

 

import java.lang.reflect.InvocationTargetException;

public class Test {

    public static void main(String[] args) throws Exception {
        Car c= new Car();
        System.out.println(new Test().getName(c));
    }

    String getName(Car car){
       System.out.print(toString());
       return car.name;
    }
}

class Car {
    String name = "Default Car";

    Car() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
    }
}

重命名重构 

重命名重构,您可以在整个代码修改符号,文件和所有引用的名字给他们。

重命名局部变量或私有方法可以很容易地内联,因为只有有限的范围受到影响。重命名类或公共方法可能会影响很多文件。在重构之前预览潜在的更改。

  1. 在编辑器中,选择要重命名的元素。如果需要重命名文件或目录,请在“ 项目”工具窗口中选择一个。

  2. 按Shift+F6或从主菜单中选择Refactor | 重命名。

  3. 您可以就地执行重命名重构,或者如果需要指定其他选项,请Shift+F6 再次按下以打开“ 重命名”对话框。例如,指定搜索元素出现的位置或要重命名的其他内容。

    重命名对话框

     

  4. 单击“ 预览”以查看潜在更改,然后单击“ 重构”。

下次调用重命名重构时,IntelliJ IDEA会记住您在“ 重命名”对话框中指定的选项 。

您无法重命名.idea项目目录,因为IntelliJ IDEA始终从具有该确切名称的目录中读取项目文件。

示例 

让我们重命名一个班级MyClass

之前

 

public class MyClass {
// some code here
}
...
public void myMethod() {
    MyClass myClass = new MyClass();
}

 

 

public class  YourClass {
// some code here
}
...
public void myMethod() {
    YourClass yourClass = new YourClass();
}

用Builder替换构造函数 

重命名重构,您可以在整个代码修改符号,文件和所有引用的名字给他们。

  1. 将插入符放置在要替换的构造函数调用上。

  2. 在主菜单或上下文菜单中,选择Refactor | 用Builder替换Constructor

  3. 在打开的对话框中,如果需要,请更改建议的setter名称。指定是否要在构建器中初始化生成的字段。
    如果指定与构造函数调用中的参数值匹配的初始值,则可以通过选择Optional Setter复选框来跳过此类参数的setter方法。您还可以指定是要创建新建还是使用现有构建器。

  4. 预览并应用更改。

示例 

之前

 

public class apples {
    public static void main(String[] args){
        variety varietyObject = new variety("Red Delicious");
        varietyObject.saying();
    }
}

// variety class

public class variety{
    private String string;

// constructor

    public variety(String name){
        string = name;
    }

    public void setName(String name) {
        string = name;
    }

    public String getName() {
        return string;
    }

    public void saying(){
        System.out.printf("On sale today : %s\n", getName());
    }
}

 

 

// variety builder is created

public class varietyBuilder {
    private String name;

    public varietyBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public variety createVariety() {
        return new variety(name);
    }
}

// varietyBuilder added instead of constructor to the main class "apples.java"

public class apples {
    public static void main(String[] args){
    variety varietyObject = new varietyBuilder().setName("Red Delicious").createVariety();
    varietyObject.saying();
    }
}

用工厂方法替换构造函数 

使用工厂方法 重构的 替换构造函数允许您隐藏构造函数并将其替换为返回类的新实例的静态方法。

  1. 选择类构造函数。

  2. 在主菜单或上下文菜单中,选择Refactor | 用工厂方法替换构造函数。

  3. 在打开的对话框中,指定工厂方法的名称以及应在其中创建方法的类。

  4. 预览并应用更改。

示例 

之前

 

// File Class.java
public class Class {
    public Class(String s) {
        ...
    }
}

// File AnotherClass.java
public class AnotherClass {
    public void method() {
        Class aClass = new Class("string");
    }
}

 

 

// File Class.java
public class Class {
    private Class(String s) {
        ...
    }
    public static createClass(String s) {
        return new Class(s);
    }
}

// File AnotherClass.java
public class AnotherClass {
    public void method() {
        Class aClass = Class.createClass("string");
    }
}

用委托替换继承 

该 替换继承随着代表团 重构让您从继承层次的一类,同时保留父的功能。IntelliJ IDEA创建一个私有内部类,它继承前一个超类或接口。通过新的内部类调用父选定的方法。

  1. 选择要重构的类。

  2. 在主菜单上或上下文菜单中,选择Refactor | 用委托替换继承。

  3. 在打开的对话框中,指定父对象,即内部类定义的名称。此外,选择将通过内部类和getter选项委派的父类的成员。

  4. 预览并应用更改。

示例 

之前

 

// File Class.java
public class Class extends SuperClass {
    public int varInt;
    public void openMethod() {
        ...
    }
}

// File SuperClass.java
public abstract class SuperClass {
    public static final int CONSTANT=0;
    public abstract void openMethod();
    public void secretMethod() {
        ...
    }
}

 

 

// File Class.java
public class Class {
    public int varInt;
    private final MySuperClass superClass = new MySuperClass();
    public SuperClass getSuperClass() {
        return superClass;
    }
    public void openMethod() {
        superClass.openMethod();
    }
    private class MySuperClass extends SuperClass {
        public void openMethod() {
            ...
        }
    }
}

// File SuperClass.java UNCHANGED
public abstract class SuperClass {
    public static final int CONSTANT=0;
    public abstract void openMethod();
    public void secretMethod() {
        ...
    }
}

用查询替换Temp  

与查询替换临时重构,您可以提取变量的初始化表达式转换的方法,并与调用所提取的方法替换对变量的所有引用。将删除变量的声明,并且可以在其他方法中使用查询方法。

int size = getActualSize() 我们只使用getActualSize() 方法操作,而不是 在整个代码中使用大小 。尽管生成的代码具有更多调用,但它更清晰,并且有助于准确识别代码中出现瓶颈的位置。

  1. 在编辑器中,将插入符号放在要重构的局部变量的名称上。

  2. 在主菜单上或上下文菜单中,选择Refactor | 用查询替换Temp。

    选择局部变量时,请确保稍后在代码中不修改其值。否则出现错误消息。

  3. 在打开的对话框中,指定提取的方法的名称和其他选项。例如,您可以声明方法static,选择将在提取的方法中使用的参数,并指定可见性选项。

  4. 单击确定。

示例 

之前

 

public void method() {
    String str ="str";
    String aString = returnString().concat(str);
    System.out.println(aString);
}

 

 

public void method() {
    String str ="str";
    System.out.println(aString(str));
}
private String aString(String str) {
    return returnString().concat(str);
}

安全删除 

IntelliJ IDEA允许您使用安全删除重构来安全地从源代码中删除文件和符号。在IntelliJ IDEA删除文件或符号之前,它会搜索用法,如果找到它们,IntelliJ IDEA会让您检查它们以进行必要的调整。

  1. 选择要删除的项目。

  2. 选择Refactor | 安全删除(Alt+Delete)。

  3. 在打开的对话框中,选择必要的选项,然后单击“ 确定”。

  4. 如果IntelliJ IDEA遇到潜在问题,则会显示“ 检测到的用量” 对话框。继续采取适当的行动。

示例 

用例

之前

安全删除参数的调用层次(这里的参数进行ibaz(int i))。

如果参数仅通过调用层次结构传递,则“ 安全删除”操作将通过整个层次结构删除该参数。IntelliJ IDEA显示相应的对话框,您可以在其中选择应删除参数的调用方法。

 

class CallHierarchySample {
    private void foo(int i) { bar(i);}
    private void bar(int i) { baz(i);}
    private void baz(int i) { }
}

 

 

class CallHierarchySample {
    private void foo() { bar();}
    private void bar() { baz();}
    private void baz() { }
}

 

安全删除调用层次结构中的foo(int i)方法(此处对方法执行)。

IntelliJ IDEA分析相应的调用层次结构并显示相应的对话框,建议您删除该调用层次结构中所有未使用的方法。

 

class CallHierarchySample {
    private void foo(int i) { bar(i);}
    private void bar(int i) { baz(i);}
    private void baz(int i) { }
}

 

 

class CallHierarchySample {



}

 

安全删除未使用的类字段 (此处执行myProperty)。

当您删除通过构造函数注入的未使用的类字段时,IntelliJ IDEA也会删除关联的构造函数参数。IntelliJ IDEA打开相应的对话框,您可以在其中检查并确认删除代码。

 

public class MyClass{
  private final MyProperty myProperty;

  public MyClass(MyProperty myProperty){
    this.myProperty = myProperty;
  }
}

 

 

public class MyClass {

  public MyClass(){
  }

}

类型迁移 

类型迁移重构允许您自动更改整个项目中的成员类型(例如,从整数到字符串)和数据流相关类型条目,如方法返回类型,局部变量,参数等。

它还允许您在数组和集合之间自动转换变量或方法返回类型。如果发现任何冲突,IntelliJ IDEA将显示相应的消息。

  1. 在编辑器中,突出显示或将插入符号放在要重构的类型上。

  2. 按Ctrl+Shift+F6主菜单上的或,选择Refactor | 类型迁移。

  3. 在打开的对话框中,指定新类型和范围以查找用法。

  4. 预览并应用更改

示例 

f: int -> String

之前

 

int f;
void bar(int i) {}
void foo() {
    bar(f);
}

 

 

String f;
void bar(String i) {}
void foo() {
    bar(f);
}

 

I<String> -> I<Integer>

之前

 

interface I<T> {
    T foo(T t);
}

class A implements I<String> {
    String myString;
    public String foo(final String s) {
        if (s == null) {
            return
               myString;
        }
        return s;
    }
}

 

 

interface I<T> {
    T foo(T t);
}

class A implements I<Integer> {
    Integer myString;
    public Integer foo(final Integer s) {
        if (s == null) {
            return
               myString;
        }
        return s;
    }
}

 

myResult: ArrayList<String> -> String[]

之前

 

public class ResultContainer {
    private ArrayList<String> myResult;
    public String[] getResult() {
        return myResult.toArray(new String[myResult.size()]);
    }
}

 

 

public class ResultContainer {
    private String[] myResult;
    public String[] getResult() {
        return myResult;
    }
}

尽可能使用接口 

使用接口尽可能 重构委托将从基类/接口派生的指定方法的执行委托给祖先类或内部类的实例,从而实现相同的接口。

  1. 在编辑器中,将插入符号放在一个类中,该类应该将方法委托给它的父类或接口。

  2. 在主菜单或上下文菜单中,选择Refactor | 尽可能使用接口。

  3. 在打开的对话框中,选择将替换当前类的用法的父对象。

  4. 要替换instanceof语句中的当前类名,请选中instanceof中的Use interface / superclass选项 。

    请注意,如果您使用instanceof语句并且未选中此复选框,则可能会收到错误的代码,例如:

    if (secondInterface instanceof Class)

    此代码将编译,但可能会产生不希望的结果。

  5. 预览并应用更改。

示例 

之前

 

// File Class.java
public class Class implements Interface {
    public void publicMethod() {
        ...
    }
    public void hiddenMethod() {
        ...
    }
}

 

 

// File Class.java UNCHANGED
public class Class implements Interface {
    public void publicMethod() {
        ...
    }
    public void hiddenMethod() {
        ...
    }
}

 

 

// File Interface.java
public interface Interface {
    int CONSTANT=0;
    void publicMethod();
}

 

 

// File Interface.java UNCHANGED
public interface Interface {
    int CONSTANT=0;
    void publicMethod();
}

 

 

// File AnotherClass.java
public class AnotherClass {
    Class firstClass;
    Class secondClass;
    public void method() {
        firstClass.publicMethod();
        firstClass.hiddenMethod();
        secondClass.publicMethod();
        if (secondClass instanceof Class) {
            ...
        }
        ...
    }
}

 

 

// File AnotherClass.java MODIFIED
public class AnotherClass {
    Class firstClass;
    Interface secondInterface;
    public void method() {
        firstClass.publicMethod();
        firstClass.hiddenMethod();
        secondInterface.publicMethod();
        if (secondInterface instanceof Interface) {
            ...
        }
        ...
    }
}

返回值 

该包裹返回值重构允许您选择的方法,以及创建一个包装类的返回值,或使用现有的,兼容的包装类。所选方法的所有返回都将被适当地包装,并且对方法的所有调用都将打开它们的返回。

如果您的设计更改为您希望方法返回的信息比最初计划的更多,则包装方法的返回非常有用。包装后,可以扩展包装类,允许从方法返回更多数据。此外,通常包装原始返回值,从而允许根据需要解耦接口和实现。

  1. 在编辑器中打开所需的类,并将插入符号放在要包装其返回值的方法中。

  2. 选择Refactor | 在主菜单或上下文菜单上换行返回值。

  3. 在打开的对话框中,指定新包装类的名称和包,或选择现有的兼容包装类。

  4. 预览并应用更改。

示例 

之前

 

class Order {
   String customer;
   String getCustomer() {
      return customer;
   }
}

 

 


class Order {
   String customer;
   Customer getCustomer() {

   }
}

class Customer {
   String id;
   Customer(String id) {
      this.id=id;
   }
}

猜你喜欢

转载自blog.csdn.net/qq_38963960/article/details/89702743
今日推荐