7

当我想引用当前范围内的方法时,我仍然需要指定类名(用于静态方法)或操作符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 没有实现这样或类似的语法?这种语法会出现什么问题吗?还是根本没有考虑过?

4

1 回答 1

6

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

有某种方法参考

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

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

就是说,允许表单::methodName缩短任何表单 1 到 3 仍然不意味着它等同于methodName(…)表达式可能引用的表单simpleName ( argopt )

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

所以说“<code>::name 应该被允许引用任何name(…)可能引用的方法”意味着结合这两个列表的可能性,你应该在做一个愿望之前三思而后行。


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

于 2015-05-18T14:01:50.750 回答