为什么必须为方法引用显式指定类/对象名称? [英] Why class/object name must be explicitly specified for method references?

查看:29
本文介绍了为什么必须为方法引用显式指定类/对象名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我想引用当前作用域中的方法时我仍然需要在 :: 之前指定类名(对于静态方法)或 this操作员.例如,我需要写:

When I want to refer to the method in the current scope I still need to specify class name (for static methods) or this before :: operator. For example, I need to write:

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 代替:

It's not so big problem for this, but sometimes look overcrowded for static methods as the class name can be quite long. It would be nice if compiler allowed me to write simply ::trimmedLength instead:

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

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

However Java-8 compiler doesn't allow this. For me it seems that it would be quite consistent if class/object name were resolved in the same manner as it's done for normal method call. This would also support static imports for method references which also can be useful in certain cases.

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

So the question is why such or similar syntax was not implemented in Java 8? Are there any problems which would arise with such syntax? Or it was not simply considered at all?

推荐答案

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

I can’t speak for the Java developers but there are some things to consider:

有某些类型的方法引用:

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

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

The compiler already has to do some work to disambiguate the forms 1 and 3 and sometimes it fails. If the form ::methodName was allowed, the compiler had to disambiguate between three different forms as it could be any of the three forms from 1 to 3.

也就是说,允许表单 ::methodName 对表单 1 到 3 中的任何一个进行快捷方式仍然不意味着它等同于表单 methodName(…) 作为表达式 simpleName ( argopt ) 可以参考

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

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

所以说::name 应该被允许引用name(…) 可能引用的任何方法"意味着结合这两个列表的可能性在许愿之前你应该三思而后行.

So saying something like "::name should be allowed to refer to any method name(…) may refer to" implies to combine the possibilities of these two listings and you should think twice before making a wish.

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

As a final note, you still have the option of writing a lambda expression like args -> name(args) which implies resolving name like a simple method invocation of the form name(args) while at the same time solving the ambiguity problem as it eliminates the option 3 of the method reference kinds, unless you write explicitly (arg1, otherargs) -> arg1.name(otherargs).

这篇关于为什么必须为方法引用显式指定类/对象名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆