IntelliJ IDEA 14.1 Introduces Extract Functional Parameter Refactoring

Anna Kozlova

              Extract Surrounding Method: You have two methods that contain nearly identical code. The variance is in the middle of the method. Extract the duplication into a method that accepts a block and yields back to the caller to execute the unique code.

Jay Fields, Shane Harvie

In Java, if we want to replace a block inside a method, the block should have a ‘known shape’ for surrounding code to be able to call it. Let’s perform a code transformation with the following example, step by step:

private void foo() {
  int i = 0;
  <selection>System.out.println(i * i);</selection>
}

  1. Call Extract Method from the block to see the signature (make sure you cancel it afterwards). In our case the signature is (int i) -> void

  1. Find an interface I, which could be implemented with this method

In our case, java.util.function.Consumer<Integer> with a shape (Integer) -> void will do.

  1. Wrap the code block with an anonymous class based on I:

new Consumer<Integer>() {
      public void accept(Integer i) {
          System.out.println(i * i);
      }
}.accept(i);

  1. Extract the anonymous class as parameter.

The result will be:

private void foo(final Consumer<Integer> consumer) {
   int i = 0;
   consumer.accept(i);
}

Now we can pass different implementations of I to the surrounding method, though everything else remains the same. The only tricky part here is to find the interface I. This is how the new Extract Functional Parameter refactoring was born.

When you call this refactoring, it asks you to choose one of the available applicable functional interfaces, and then performs the rest automatically:

Screen Shot 2015-01-23 at 11.55.56.png

With the introduction of lambdas and method references, many functional interfaces were added. To distinguish them from sporadic single-method interfaces that could evolve, IntelliJ IDEA requires them to be marked with @FunctionalInterface or belong to well-known libraries (e.g. Guava, Apache Collections, etc.).

Extract Functional Parameter is already available in IntelliJ IDEA 14.1 EAP. Do give it a try and tell us what you think. Share your feedback on the discussion forum and in our issue tracker.

Develop with Pleasure!

Comments below can no longer be edited.

7 Responses to IntelliJ IDEA 14.1 Introduces Extract Functional Parameter Refactoring

  1. ks says:

    February 10, 2015

    Cool feature!

    “To distinguish them from sporadic single-method interfaces that could evolve, IntelliJ IDEA requires them to be marked with @FunctionalInterface or belong to well-known libraries (e.g. Guava, Apache Collections, etc.).”

    To prioritize well-known would be one thing but to require @FunctionalInterface seems a bit much. I’d like to be able to search and pick from the ‘sporadic’ interfaces defined by my project w/o having to go through and annotate everything (as simple as it may be to do so). The available interfaces list should be: @FunctionalInteface, followed by well-known, followed by project interfaces, followed by ‘sporadic’ one-offs.

  2. Anna Kozlova says:

    February 10, 2015

    Thanks!

    Actually at first I thought exactly like you. Then I’ve got 1000 single-method interfaces in IDEA project and each of them should be checked: this slowed down everything a lot and didn’t bring much value: I extract strategies into “well-known” interfaces rather than e.g. into listeners, do you?

    Anna

    • ks says:

      February 10, 2015

      Maybe if the current project interfaces were considered ‘well-known’ ?? I see your point that scanning dozens/hundreds of dependency jars would be inhibitive.

  3. Lars says:

    March 12, 2015

    Please make this for Scala!

  4. Alex Dommasch says:

    July 7, 2015

    It would be great to have “Extract Functional Variable” as well (e.g., convert a block of code into a local-variable lambda). Use case: having similar code patterns scattered around that have variable “cores”; would like to extract cores into lambdas in each case, and then extract method once (and let IDEA find code duplicates).

    I managed to abuse “Extract Method”, “Extract Functional Variable”, “Inline Method” in various combinations to achieve the same effect, but it would be nice to have it more direct. (And what would be *really* amazing is if IDEA could identify potential extracted lambdas automatically when looking for code duplicates – but that’s a lot to ask.)

Subscribe

Subscribe for updates