IntelliJ IDEA 2025.1 Help

提取形参

Extract Parameter 重构可以让您提取一个新的参数到方法中。

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

  1. 在编辑器中,将文本光标放置在您想要引入为参数的表达式内,然后按 Ctrl+Alt+P 或者在主菜单中转到 重构 | 提取 | 参数

    或者,选择代码片段。 在显示的 工具栏中,点击 提取 并选择 形参

  2. 如果您想提取一个功能参数,请按 Ctrl+Alt+Shift+P 或进入主菜单中的 重构 | 提取 | 函数参数

  3. 指定参数名称,并在 Extract Parameter 弹窗中选择必要的选项。 当您调用此重构时,IntelliJ IDEA 还会显示 齿轮图标 ,您可以用它来配置更多选项。

    引入参数:更多选项

    例如, 如果您不想更改现有的方法调用,请选择 通过重载方法委托 复选框。

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

提取参数示例

在提取新参数时,您可以将参数引入到现有方法中,或者使用 通过重载方法委托 选项来保存原有方法并定义一个带有您参数的新方法。

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

之前

之后

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(); } }

之前

之后

object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(): String { return "Hello, World!".toUpperCase() } }
object HelloWorldPrinter { fun print() { println(generateText("Hello, World!")) } private fun generateText(text: String): String { return text.toUpperCase() } }

现在让我们使用 通过重载方法委托。 在这种情况下,会创建一个新的重载方法,并在该方法(第二个 generateText() 方法)的定义中提取新的参数。 现有 generateText() 方法的签名没有改变。 然而,这个方法本身已经被修改。 现在,它调用了新的 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(); } }

之前

之后

object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(): String { return "Hello, World!".toUpperCase() } }
// if you selected the "Introduce default value" option object HelloWorldPrinter { fun print() { println(generateText()) } private fun generateText(text: String = "Hello, World!"): String { return text.toUpperCase() } }

函数参数示例

让我们在 System.out.println(s); 中对 Hello.printHello() 执行重构。

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

因此,选定的片段 System.out.println(s); 基于接口 Person 被封装到一个匿名类中。 此匿名类作为参数传递给 printHello() 内的 printText()

Person 作为参数添加到 printHello() ,最初选择的代码片段被替换为对接口 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); } }); } }

提取参数重构的特别注意事项

  • 如果您希望某个字段在方法声明中作为新参数提供,则在方法调用中,该字段将作为类实例的字段呈现。

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

  • 如果您为 Extract Parameter 重构使用具有 getter 的字段,您将会看到一个扩展对话框。 对话框有一个选项组 用其 getter 替换表达式中使用的字段:

    • 不要替换: 任何字段都不会被其 getter 调用替换。

    • 替换上下文没有使用的字段 :只有无法从使用上下文直接访问的字段会被替换为对 getter 的调用。

    • 替换所有字段 :所有字段将被调用 getter 方法替换。

  • 将重构应用于局部变量时,将调用 Extract Parameter 对话框,并附带额外的复选框:

    • 替换所有出现的情况(<number_of_occurrences> 次出现) :如果启用,所有选定变量的出现将被替换为参数,并且会启用 删除变量定义 复选框。 否则,只有选定的变量使用将被替换为参数。

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

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

副作用

使用 Extract Parameter 进行重构时,如果应用于类实例或实际为方法参数的表达式,可能会有意外的副作用。 例如,对于这样的代码:

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 可以成功地使用一个临时变量,解决诸如增量/减量/赋值操作和 new 关键字使用等情况。 例如:

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 已创建,调用方法所需的所有参数都通过此变量提供。

提取参数对话框(Java)

使用此对话框指定提取参数的设置。

条目

描述

类型参数

指定新参数的类型。 通常,您不需要更改 IntelliJ IDEA 建议的类型。

名称

请指定新参数的名称。

替换所有匹配项

选择此选项以替换方法中选定表达式的所有出现。

声明 final

选择此选项以声明参数 final

通过重载方法委托

选择此选项以保持现有方法调用不变。

因此,将创建一个新的重载方法,并将新参数添加到此方法的定义中。 具有旧签名的方法将被保留。 对新方法的调用将被添加到旧方法中。 在此调用中,必要的值(或表达式)将传递到新方法。

如果表达式包含对具有 getter 的类字段的直接调用,则可以使用以下选项。

不要替换

选择此选项以直接调用字段,而不考虑作用域上下文。

替换上下文没有使用的字段

选择此选项,仅在字段直接不可访问的情况下调用 getter。

替换所有字段

选择此选项以调用 getter。

重构后的表达式包含局部变量时,您可以使用以下选项。

删除变量定义

选择此选项以删除局部变量的定义。

使用变量初始值设定项初始化形参

选择此选项以在更正的方法调用中使用所选变量的默认值。

Groovy 中提取参数对话框

使用此对话框指定与 Groovy 中提取参数重构相关的选项和设置。

条目

描述

类型

指定新参数的类型。 通常,您不需要更改 IntelliJ IDEA 建议的类型。

名称

请指定新参数的名称。

声明 final

选择此选项以声明参数 final

通过重载方法委托

选择此选项以保持现有方法调用不变。

因此,将创建一个新的重载方法,并将新参数添加到此方法的定义中。 具有旧签名的方法将被保留。 对新方法的调用将被添加到旧方法中。 在此调用中,必要的值(或表达式)将传递到新方法。

移除不再使用的参数 <name>

选中此复选框以移除参数。

使用显式 return 语句

如果该方法返回一个值,则此复选框处于活动状态。 如果它是方法中的最后一个 return 语句,您可以省略 return 关键字。 如果选择这个 复选框,关键字将被返回。

形参

在此区域,选择要传递给新方法/函数的参数。

上移 / 下移

使用这些按钮更改参数的顺序。

签名预览

在此只读字段中,查看新方法/函数的声明。

最后修改日期: 2025年 4月 24日