【问题标题】:Why class/object name must be explicitly specified for method references?为什么必须为方法引用显式指定类/对象名称?
【发布时间】:2015-05-15 05:06:53
【问题描述】:

当我想引用当前范围内的方法时,我仍然需要 在:: 之前指定类名(用于静态方法)或this 操作员。比如我需要写:

import java.util.stream.Stream;

public class StreamTest {
    public static int trimmedLength(String s) {
        return s.trim().length();
    }

    public static void main(String[] args) {
        System.out.println(Stream.of("  aaa  ", "  bb ", " c ")
                .mapToInt(StreamTest::trimmedLength).sum());
    }
}

这对this 来说不是什么大问题,但有时静态方法看起来过于拥挤,因为类名可能很长。如果编译器允许我改为简单地写::trimmedLength,那就太好了:

public static void main(String[] args) {
    System.out.println(Stream.of("  aaa  ", "  bb ", " c ")
            .mapToInt(::trimmedLength).sum());
}

但是 Java-8 编译器不允许这样做。对我来说,如果以与普通方法调用相同的方式解析类/对象名称,这似乎是非常一致的。这也将支持方法引用的静态导入,这在某些情况下也很有用。

那么问题是为什么 Java 8 中没有实现这样或类似的语法?这种语法会出现什么问题吗?还是根本没有考虑过?

【问题讨论】:

  • 您是否查看过 JCP 中有关此语法的讨论?我敢打赌,您可以找到很多关于这个和其他想法的信息。
  • 不,我没有。如果您指出关于我的问题的确切消息/意见,那就太好了。

标签: java java-8 method-reference


【解决方案1】:

我不能代表 Java 开发人员,但有一些事情需要考虑:

有一定的kind of method references

  1. 对静态方法的引用,例如ContainingClass::staticMethodName
  2. 对特定对象的实例方法的引用,例如containingObject::instanceMethodName
  3. 对特定类型的任意对象的实例方法的引用,例如ContainingType::methodName
  4. 对构造函数的引用,例如ClassName::new

编译器已经做了一些工作来消除形式 1 和 3 以及sometimes it fails 的歧义。如果允许::methodName 形式,编译器必须消除三种不同形式之间的歧义,因为它可以是从 1 到 3 的三种形式中的任何一种。

也就是说,允许表单 ::methodName 将表单 1 到 3 中的任何一个快捷方式仍然不意味着它等同于表单 methodName(…),因为表达式 simpleName ( arg<sub>opt</sub> ) 可能指代

  • 当前类或其超类和接口范围内的实例方法
  • 当前类或其超类范围内的 static 方法
  • 外部类或其超类和接口范围内的实例方法
  • 外部类或其超类范围内的 static 方法
  • 通过import static 声明的static 方法

所以说“应该允许::name 引用name(…) 可能引用的任何方法”之类的话意味着将这两个列表的可能性结合起来,在许愿之前你应该三思而后行。


最后一点,您仍然可以选择编写像 args -&gt; name(args) 这样的 lambda 表达式,这意味着像 name(args) 形式的简单方法调用一样解析 name,同时解决歧义问题消除了方法引用类型的选项 3,除非您明确编写 (arg1, otherargs) -&gt; arg1.name(otherargs)

【讨论】:

  • 感谢您的详细解答。我希望 Java 开发人员能回答,但可能我的问题对他们来说不是很有趣。
  • @Holger 在使用了过去 3 个月的方法参考之后,我也倾向于以 Tagir 的方式思考。很难理解,仅仅因为编译器必须做更多的任务,就省略了预期的方法引用形式。相反,编译器可以尽力解决。如果无法解决,它总是可以要求以完整形式消歧。
  • @Mrinal K. Samanta:不仅编译器必须进行消歧。人类读者也必须这样做。对方法目标有错误的想法会造成比少打几个字母所能弥补的更大的伤害。
  • 对于任何寻找的人,这里有来自@Brian Goetz 的回复:stackoverflow.com/questions/31665393/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
相关资源
最近更新 更多