当前位置: 首页 > 面试题库 >

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

羊舌承
2023-03-14
问题内容

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


问题答案:

我不能代表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

因此说“ ::name应该允许引用任何name(…)可能引用的方法”之类的东西意味着要结合这两个清单的可能性,您在许愿之前应三思而后行。

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



 类似资料:
  • 问题内容: 尽管Java中的所有类都是Object类的子类,但是与其他对象类型不同,但是如果没有强制类型转换,则不能将Object类型的引用变量分配给任何其他引用类型。 例如: 问题答案: 您想知道为什么我们使用显式类型转换。这就是关于继承的一切- 让我来清除此-让我们有两个类 A类 和 B类 。和 B类 是子类的 类A 。这意味着 Class B 具有 Class A的 所有功能,这意味着 Cl

  • 问题内容: 我正在向我的朋友解释OOP。我无法回答这个问题。(我有多可耻? 我只是想逃避,因为OOP描绘了现实世界。在现实世界中,父母可以容纳孩子,但孩子不能容纳父母。OOP也是如此。我知道它很愚蠢。:P 为什么此陈述无效? 因为aChild的成员是aParent成员的超集。那为什么孩子不能容纳父母。 问题答案: 正是因为aChild是aParent功能的超集。你可以写: 因为每只狐狸都是动物。但

  • 问题内容: 我开始学习Go,但对以下内容有所了解: 失败的原因是: 考虑到实现的事实,我不明白为什么Go不接受签名。有人可以帮忙解释吗? 问题答案: 我认为您对界面的理解不够充分。Interface {}本身就是一种类型。它由两部分组成:基础类型和基础值。 Golang没有重载。Golang类型系统按名称匹配,并且要求类型一致 因此,当您定义将接口类型作为参数的函数时: 这与采用int类型的函数不

  • 问题内容: 如果我删除in : github.com/creating_web_app_go/main.go:8:不能在http.HandleFunc的参数中使用func文字(类型func(http.ResponseWriter,http.Request))作为func(http.ResponseWriter,* http.Request)类型。 我对Go和指针都很陌生。 所以问题是,为什么必须是

  • 问题内容: 以下代码在该行生成此错误消息。 这行有多个标记 -实现android.view.View.OnClickListener.onClick -new View.OnClickListener(){}类型的onClick(View)方法必须覆盖超类方法 我不明白为什么。这段代码摘自我所见过的众多示例。什么可能是错的? 问题答案: 检查项目的属性,并验证 Java Compiler- > C

  • 我正在使用GlassFish 3.1.2和Eclipse4.2。如果使用指定一个JTA事务类型,我可以很高兴地添加一个新类,如果我放置批注,该类将作为实体读取。 现在,如果我将事务类型更改为,将数据源更改为非JTA,并且添加必要的代码来检索和,在这里我将调用和。为了解决这个问题,我必须将我的实体添加到persistence.xml中列出的类中。 现在,这解决了我的问题,但我不明白为什么。根据规范,