4

I have a ton of classes with one method (half of them don't use their parameter and thus name it underscore), and I just switched to Java 8. Now I want to replace them with lambdas.

Here is my code:

interface I {
  void stuffHappened(Integer howManyStuff);
}

public class A {
  void go() {
    I i = new I() {
      public void stuffHappened(Integer _) {
        System.out.println("woah!!");
      }
    };
  }
}

And after:

interface I {
  void stuffHappened(Integer howManyStuff);
}

public class A {
  void go() {
    I i = _ -> System.out.println("woah!!");
  }
}

As you can see, it is apparently no longer valid, claiming the use of "_" as the parameter name is no longer valid. But then why did it allow this refactor in the first place? And why does it work with anonymous classes, but not lambdas? Is this really a new rule? Or is it some sort of discrepancy in IDEA?

I'm using Intellij-IDEA (first time using it), well actually, Android Studio (Beta) 0.8.1 (using retrolambda to permit lambdas on android), which I think uses IDEA.

Dog
  • 7,707
  • 8
  • 40
  • 74

2 Answers2

8

Prior to Java 8, a single underscore _ was a valid identifier. Starting with Java 8, the underscore is disallowed, in order to allow for the future possibility of having it be something other than an ordinary identifier. See this message from Brian Goetz for the explanation.

Use of an underscore in existing (pre-lambda) code will generate a warning, but use of an underscore as a lambda formal parameter name will generate an error. As Brian put it, "since there is no existing code with lambdas."

In your example, the formal parameter _ in your anonymous inner class is legal code, though it should generate a warning. Refactoring this code into a lambda that uses _ will make it illegal! Since IntelliJ IDEA is refactoring this code, it should be aware of this rule, and it should offer to rename the parameter name to something else.

This could be viewed as a bug, or at least an need for an enhancement, in IDEA's refactoring mechanism.

Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
4

Lambdas don't allow _ as a parameter name, but existing constructs do.

From JLS 15.27.1. Lambda Parameters:

It is a compile-time error if a lambda parameter has the name _ (that is, a single underscore character).

The use of the variable name _ in any context is discouraged. Future versions of the Java programming language may reserve this name as a keyword and/or give it special semantics.

I would suggest either renaming the parameters to __, $, or to save space, since you're already using unicode,_ (though perhaps the latter is linguistic abuse - I don't know what that actual code point is intended for).

Harold R. Eason
  • 563
  • 2
  • 9