Extract Parameter
The Extract Parameter refactoring lets you extract a new parameter to a method.
You can also use the Extract Functional Parameter refactoring. In this case, IntelliJ IDEA analyzes the selected code, finds out what the method signature would be for the extracted fragment, finds all functional interfaces with this method signature and wraps the code fragment with a anonymous class based on the selected interface and uses this anonymous class as a parameter.
In the editor, position the caret within the expression that you want to introduce as a parameter.
Press Ctrl+Alt+P or from the main menu, select
. If you want to extract a functional parameter, press Ctrl+Alt+Shift+P or from the main menu, select .Specify a name of the parameter, select the necessary options in the Extract Parameter popup. For example, if you don't want to change the existing method calls, select the Delegate via overloading method checkbox.
If you need, press Shift+Tab to change a type of the new parameter. (If, at this step, you want to return to editing the parameter name, press Tab.)
Extract parameter examples
When extracting a new parameter you can either introduce a parameter into the existing method or use the Delegate via overloading method option to save the original method and define a new method with your parameter.
Let's replace the string value "Hello, World!"
in the method generateText ()
with the new parameter text
. The value "Hello, World!"
is passed to the method in the updated method call generateText("Hello, World!")
.
Before | After |
---|---|
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();
}
}
|
Before | After |
---|---|
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()
}
}
|
Now let's use Delegate via overloading method. In this case, a new overloading method is created and the new parameter is extracted in the definition of this method (the second of the generateText()
methods). The signature of the existing generateText()
method is not changed. However, the method itself has been modified. Now, it calls the new generateText()
method and passes the value "Hello, World!"
to it in this call. Note that the existing call of generateText()
(in the method print()
) is not changed.
Before | After |
---|---|
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();
}
}
|
Before | After |
---|---|
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()
}
}
|
Functional parameter examples
Let's perform the refactoring on System.out.println(s);
within Hello.printHello()
.
IntelliJ IDEA finds all functional interfaces with the appropriate method signature (String) -> void
and suggests that you select one of them. (In this example, the interface Person
is selected.)
As a result, the selected fragment System.out.println(s);
is wrapped with an anonymous class based on the interface Person
. This anonymous class is passed as a parameter to the call to printHello()
within printText()
.
Person
is added as a parameter to printHello()
and the initially selected code fragment is replaced with the call to the method of the interface sayHello()
.
Before | After |
---|---|
@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);
}
});
}
}
|
Special notes for the Extract Parameter refactoring
If you want a field to be provided as a new parameter in the method declaration, in a method call this field will be presented as a field of a class instance.
If a class member is inaccessible (for instance, in the example above the field is private), it will be inserted in a method call but will be highlighted as an error making this file uncompilable.
If you use for the Extract Parameter refactoring a field with a getter, you will be prompted with an extended dialog. The dialog has an option group Replace fields used in expressions with their getters:
Do not replace: None of the fields will be replaced with calls to the getter.
Replace fields inaccessible in usage context: Only the fields that cannot be directly accessed from the usage context will be replaced with calls to the getter.
Replace all fields: All fields will be replaced with calls to the getter.
Applying the refactoring on a local variable will call the Extract Parameter dialog box with additional checkboxes:
Replace all occurrences (<number_of_occurrences> occurrences): If enabled, all occurrences of the selected variable will be replaced with a parameter and the Delete variable definition checkbox is enabled. Otherwise, only the selected variable usage will be replaced with a parameter.
Delete variable definition: If enabled, the variable definition will be deleted.
Use variable initializer to initialize parameter: If enabled, the variable initializer will be used to initialize the parameter in the method call.
Side effects
Using the Extract Parameter refactoring can have unexpected side effects if applied on class instances or expressions which are actual method parameters. For instance, in case of such code:
The code after refactoring applied to the field field
:
The iterator value is increased twice which is, actually, not the behavior you would expect.
However, IntelliJ IDEA can use a temporary variable successfully and resolve such cases as increment/decrement/assignment operations and the new keyword usage. For instance:
Same code after refactoring looks as follows:
The new variable list
was created and all parameters used for the method call are provided using this variable.