为什么必须为方法引用显式指定类/对象名称?

2024-04-10

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

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 中没有实现这样或类似的语法?这样的语法会产生什么问题吗?还是根本就没有考虑过?


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

有一定的方法参考类型 http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html:

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

编译器已经必须做一些工作来消除形式 1 和 3 的歧义,有时会失败 https://stackoverflow.com/q/21873829/2711488。如果表格::methodName如果允许,编译器必须消除三种不同形式之间的歧义,因为它可以是从 1 到 3 的三种形式中的任何一种。

That said, allowing the form ::methodName to short-cut any of the form 1 to 3 still wouldn’t imply that it is equivalent to the form methodName(…) as the expression simpleName ( argopt ) may refer to

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

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


最后一点,您仍然可以选择编写 lambda 表达式,例如args -> name(args)这意味着解决name就像表单的简单方法调用一样name(args)同时解决歧义问题,因为它消除了方法引用类型的选项 3,除非您显式编写(arg1, otherargs) -> arg1.name(otherargs).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么必须为方法引用显式指定类/对象名称? 的相关文章

随机推荐