Java 8 Streams map API-方法参考的解释
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java 8 Streams map API-方法参考的解释,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3312字,纯文字阅读大概需要5分钟。
内容图文
样例代码:
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,它不带任何参数,基本上是Supplier< T>功能界面. [1]
> MyClass :: instanceMethod,其采用类型为Outer的参数,并且是Function< T,R>功能接口. [1]
已验证.然后,映射函数如何知道将选项(1)中的函数应用于流的对象,但是将流对象传递给选项(2)中的函数?
[1] https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
解决方法:
首先,map方法本身不知道如何处理方法引用.那就是编译器的工作.在这两种情况下,地图均预期:
Function<? super PackageName.outer,? extends Integer>
对于您的特定问题,根据docs的两个方法引用都是对特定对象的实例方法的引用
强烈建议阅读有关编译器如何处理lambda和方法引用并将其转换为字节码this document的信息.与您的问题最相关的部分(重点是我的总结):
When the compiler encounters a lambda expression, it first lowers
(desugars) the lambda body into a method whose argument list and
return type match that of the lambda expression, possibly with some
additional arguments (for values captured from the lexical scope, if
any.) At the point at which the lambda expression would be captured,
it generates an invokedynamic call site, which, when invoked, returns
an instance of the functional interface to which the lambda is being
converted. This call site is called the lambda factory for a given
lambda. The dynamic arguments to the lambda factory are the values
captured from the lexical scope. The bootstrap method of the lambda
factory is a standardized method in the Java language runtime library,
called the lambda metafactory. The static bootstrap arguments capture
information known about the lambda at compile time (the functional
interface to which it will be converted, a method handle for the
desugared lambda body, information about whether the SAM type is
serializable, etc.)Method references are treated the same way as lambda expressions,
except that most method references do not need to be desugared into a
new method; we can simply load a constant method handle for the
referenced method and pass that to the metafactoryInstance-capturing method reference forms include bound instance
method references (s::length, captured with reference kind
invokeVirtual)
您的2种情况的字节码为:
>外部::实例方法
// 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;
注意,尽管第二行在第二种情况下更为复杂,但最后一行是相同的.在这两种情况下,编译器只会看到一个接受外部函数并返回整数的函数.并符合地图的预期.
在语言规范15.13 Method Reference Expressions中描述了方法引用.在15.13.3 Run-Time Evaluation of Method References中提到了方法引用的目标引用是该方法的隐式第一参数的事实.
If the compile-time declaration is an instance method, then the target
reference is the first formal parameter of the invocation method.
Otherwise, there is no target reference
内容总结
以上是互联网集市为您收集整理的Java 8 Streams map API-方法参考的解释全部内容,希望文章能够帮你解决Java 8 Streams map API-方法参考的解释所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。