不能用下划线重构方法作为lambdas的参数?

时间:2014-07-15 05:40:08

标签: java android intellij-idea lambda java-8

我有一个带有一个方法的类(其中一半不使用他们的参数,因此将其命名为下划线),我只是切换到Java 8.现在我想用lambdas替换它们。

这是我的代码:

interface I {
  void stuffHappened(Integer howManyStuff);
}

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

之后:

interface I {
  void stuffHappened(Integer howManyStuff);
}

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

如您所见,它显然已不再有效,声称使用“_”作为参数名称不再有效。但那么为什么它首先允许这个重构呢?为什么它适用于匿名类,而不是lambdas?这真的是一条新规吗?或者它在IDEA中是否存在某种差异?

我正在使用Intellij-IDEA(第一次使用它),实际上是Android Studio(Beta)0.8.1(使用retrolambda允许在Android上使用lambdas),我认为它使用IDEA。

2 个答案:

答案 0 :(得分:7)

在Java 8之前,单个下划线_是有效的标识符。从Java 8开始,不允许使用下划线,以便将来可能使其成为普通标识符以外的其他内容。有关说明,请参阅此message from Brian Goetz

在现有(pre-lambda)代码中使用下划线将生成警告,但使用下划线作为lambda形式参数名称将生成错误。正如Brian所说,“因为没有lambda的现有代码。”

在您的示例中,匿名内部类中的形式参数_是合法代码,但它应该生成警告。将此代码重构为使用_的lambda将使其成为非法!由于IntelliJ IDEA正在重构此代码,因此它应该知道此规则,并且它应该提供将参数名称重命名为其他名称。

在IDEA的重构机制中,这可能被视为一个错误,或者至少需要一个增强功能。

答案 1 :(得分:4)

Lambdas不允许_作为参数名称,但现有的构造可以。

来自JLS 15.27.1. Lambda Parameters

  

如果lambda参数的名称为_(那个,那么这是一个编译时错误   是,一个下划线字符。)

     

不鼓励在任何上下文中使用变量名_。未来   Java编程语言的版本可以保留此名称作为   关键字和/或赋予它特殊的语义。

我建议将参数重命名为__$或节省空间,因为您已经使用了unicode,_(尽管后者可能是语言的滥用 - 我不知道实际代码点的用途是什么。