提取形参
Extract Parameter 重构可以让您提取一个新的参数到方法中。
您也可以使用 提取功能参数 重构功能。 在这种情况下,IntelliJ IDEA 会分析选中的代码,确定提取片段的方法签名,找到具有此方法签名的所有功能接口,并使用基于选定接口的匿名类包装代码片段,并使用此匿名类作为参数。
在编辑器中,将文本光标放置在您想要引入为参数的表达式内,然后按 Ctrl+Alt+P 或者在主菜单中转到 。
或者,选择代码片段。 在显示的 工具栏中,点击 提取 并选择 形参。
如果您想提取一个功能参数,请按 Ctrl+Alt+Shift+P 或进入主菜单中的 。
指定参数名称,并在 Extract Parameter 弹窗中选择必要的选项。 当您调用此重构时,IntelliJ IDEA 还会显示
,您可以用它来配置更多选项。

例如, 如果您不想更改现有的方法调用,请选择 通过重载方法委托 复选框。
如果需要,请按 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 进行重构时,如果应用于类实例或实际为方法参数的表达式,可能会有意外的副作用。 例如,对于这样的代码:
重构后的代码应用到了字段 field:
迭代器的值增加了两次,这实际上不是预期的行为。
然而,IntelliJ IDEA 可以成功地使用一个临时变量,解决诸如增量/减量/赋值操作和 new 关键字使用等情况。 例如:
重构后的代码如下所示:
新的变量 list 已创建,调用方法所需的所有参数都通过此变量提供。
提取参数对话框(Java)
使用此对话框指定提取参数的设置。
条目 | 描述 |
|---|---|
类型参数 | 指定新参数的类型。 通常,您不需要更改 IntelliJ IDEA 建议的类型。 |
名称 | 请指定新参数的名称。 |
替换所有匹配项 | 选择此选项以替换方法中选定表达式的所有出现。 |
声明 final | 选择此选项以声明参数 |
通过重载方法委托 | 选择此选项以保持现有方法调用不变。 因此,将创建一个新的重载方法,并将新参数添加到此方法的定义中。 具有旧签名的方法将被保留。 对新方法的调用将被添加到旧方法中。 在此调用中,必要的值(或表达式)将传递到新方法。 |
如果表达式包含对具有 getter 的类字段的直接调用,则可以使用以下选项。 | |
不要替换 | 选择此选项以直接调用字段,而不考虑作用域上下文。 |
替换上下文没有使用的字段 | 选择此选项,仅在字段直接不可访问的情况下调用 getter。 |
替换所有字段 | 选择此选项以调用 getter。 |
重构后的表达式包含局部变量时,您可以使用以下选项。 | |
删除变量定义 | 选择此选项以删除局部变量的定义。 |
使用变量初始值设定项初始化形参 | 选择此选项以在更正的方法调用中使用所选变量的默认值。 |
Groovy 中提取参数对话框
使用此对话框指定与 Groovy 中提取参数重构相关的选项和设置。
条目 | 描述 |
|---|---|
类型 | 指定新参数的类型。 通常,您不需要更改 IntelliJ IDEA 建议的类型。 |
名称 | 请指定新参数的名称。 |
声明 final | 选择此选项以声明参数 |
通过重载方法委托 | 选择此选项以保持现有方法调用不变。 因此,将创建一个新的重载方法,并将新参数添加到此方法的定义中。 具有旧签名的方法将被保留。 对新方法的调用将被添加到旧方法中。 在此调用中,必要的值(或表达式)将传递到新方法。 |
移除不再使用的参数 <name> | 选中此复选框以移除参数。 |
使用显式 return 语句 | 如果该方法返回一个值,则此复选框处于活动状态。 如果它是方法中的最后一个 return 语句,您可以省略 |
形参 | 在此区域,选择要传递给新方法/函数的参数。 |
上移 / 下移 | 使用这些按钮更改参数的顺序。 |
签名预览 | 在此只读字段中,查看新方法/函数的声明。 |