当前位置: 首页 > 知识库问答 >
问题:

Java 8 Streams map API-方法引用的解释

郎思远
2023-03-14
class Outer {
    public Integer i;

    Outer(Integer i) {
        this.i = i;
    }

    public int getVal() { return i; }
}

class MyClass {

    public Integer f(Outer o) { return o.getVal();};

    public void main() {

        MyClass g = new MyClass();

        List<Integer> l1 = Arrays.asList(new Outer(2)).stream().map(g::f).collect(Collectors.toList());
        List<Integer> l2 = Arrays.asList(new Outer(2)).stream().map(Outer::getVal).collect(Collectors.toList());
    }
}

的方法引用之一

>

  • outer::instanceMethod,它不接受参数,基本上是供应商 函数接口。[1]

    MyClass::InstanceMethod,它接受outer类型的参数,是函数 函数接口。[1]

    是有效的。那么map函数如何知道如何将选项(1)中的函数应用于流对象,但将流对象传递给选项(2)中的函数?

    [1]https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

  • 共有1个答案

    酆意智
    2023-03-14

    首先,map方法本身不知道如何处理方法引用。那是编译器的工作。在这两种情况下,map都需要:

    Function<? super PackageName.outer,? extends Integer>
    

    对于您的特定问题,根据文档,两个方法引用都是对特定对象的实例方法的引用

    关于编译器如何处理lambda和方法引用并将它们转换为字节码,强烈建议阅读本文档。与你的问题最相关的部分(强调我的总结):

    当编译器遇到lambda表达式时,它首先将lambda主体降低(desugars)到一个方法中,该方法的参数列表和返回类型与lambda表达式的参数列表和返回类型匹配,可能会使用一些额外的参数(如果有的话,用于从词法范围捕获的值)在捕获lambda表达式时,它生成一个invokedynamic调用站点,当调用该站点时,返回将lambda转换到的函数接口的实例。对于给定的lambda,此调用站点称为lambda工厂。lambda工厂的动态参数是从词法范围捕获的值。lambda factory的引导方法是Java语言运行时库中的一种标准化方法,称为lambda元actory。静态引导参数捕获编译时已知的关于lambda的信息(它将转换到的函数接口、解集的lambda正文的方法句柄、关于SAM类型是否可序列化的信息,等等)

    方法引用与lambda表达式的处理方式相同,只是大多数方法引用不需要被解析为新方法;我们可以简单地为被引用的方法加载一个常量方法句柄,并将其传递给元actory

    实例捕获方法引用表单包括绑定的实例方法引用(S::length,用引用类型invokeVirtual捕获)

    两种情况的字节码是:

    >

  • outer::instanceMethod

    // handle kind 0x5 : INVOKEVIRTUAL
    PackageName/outer.getVal()I, 
    (LPackageName/outer;)Ljava/lang/Integer;
    

    MyClass::InstanceMethod

    // handle kind 0x5 : INVOKEVIRTUAL
    PackageName/MyClass.f(LPackageName/outer;)Ljava/lang/Integer;, 
    (LPackageName/outer;)Ljava/lang/Integer;
    

  •  类似资料:
    • 我举了以下例子: 例。1起作用是因为类中的方法具有与接口中的方法相同的方法签名和返回类型。 但为什么Ex.2有效?类中的方法,与Method签名不同,我希望在这里得到编译时错误。

    • 问题内容: 请解释一下 与功能界面兼容。 方法已在功能接口中实现。 正在工作 请单独解释所有要点。 问题答案: __ is的 等效 lambda表达式 这是 特定类型的任意对象的实例方法的 命名 引用 的功能之一。 __ 考虑以下示例, 输出值 请注意,这对于call even 方法不是静态的有效。 当你调用该方法的功能界面,你仍然有两个参数,其是与并为有效的lambda表达式可以有参数,所以你的

    • 我错过了Java的一次讲座,主题是类、方法、构造函数等。作业是一项任务: 创建一个类Person,其对象描述人员,并且只包含两个字段:name(String)和生年(int)。在此类中,定义 > 建造师姓名和出生年份; 构造函数只取名称并将出生年份设置为默认值1990; 方法是如果此人是女性,则女性返回true(我们不太明智地假设只有女性和所有女性的名字以字母“a”结尾);否则该方法返回false

    • 为什么下面的工作? 当我阅读java.util.stream.stream的方法描述时

    • 主要内容:1.方法引用,2.方法引用与lambda,3.方法引用的使用1.方法引用 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。 方法引用通过方法的名字来指向一个方法。 方法引用可以使语言的构造更紧凑简洁,减少冗余代码。 方法引用使用一对冒号 :: 2.方法引用与lambda 3.方法引用的使用 静态方法引用 静态方法

    • 本文向大家介绍使用Java8中的方法引用来引用实例方法,包括了使用Java8中的方法引用来引用实例方法的使用技巧和注意事项,需要的朋友参考一下 Java中的Lambda表达式使您可以将功能作为参数传递给方法。您也可以使用lambda表达式调用现有方法。 方法引用是简单,易于阅读的lambda表达式,可通过lambda表达式中的名称来调用/引用和现有方法。 语法 以下是在Java中引用实例方法的语法