方法引用在Java中是如何解析的

huangapple go评论70阅读模式
英文:

How does the method reference resolve in Java

问题

Function<String, Integer> f = Integer::parseInt;

Integer i = f.apply("100");

在调用 f.apply 时,这会转变为使用 Integer.parseInt 吗?

英文:
Function&lt;String, Integer&gt; f = Integer::new;
		
Integer i = f.apply(&quot;100&quot;);

How this turns to use Integer.parseInt when we are calling f.apply?

答案1

得分: 2

我推测你的问题是:“javac如何知道在这里调用parseInt”?

你的代码片段有问题,泛型丢失了。目前的代码无法编译,因为引用是模糊的。如果你将泛型添加回去,它将能够编译并正常工作:

Function<String, Integer> f = Integer::new;
Integer i = f.apply("100");

忘记新的 :: 语法或 Function 部分,它们是误导信息。

所以,让我们简化一下:

Integer i = new Integer("100");

这是有效的Java代码;i 将会保存值 100。

它能够工作是因为... 那个构造函数是存在的。它被规定的行为与使用基数为10的 Integer.parseInt 完全相同,而且它已经被弃用,有两个很好的理由:[A] 调用 new Integer(),无论使用什么值,都已经被弃用(使用 Integer.valueOf),以及 [B] 直接调用parseInt。

英文:

I surmise that your question is: "How does javac know to invoke parseInt here"?

Your snippet is broken; the generics fell off. As is, your code won't compile, as the reference is ambiguous. If you add it back in, it will compile and works as normal:

Function&lt;String, Integer&gt; f = Integer::new;
Integer i = f.apply(&quot;100&quot;);

Forget the new :: syntax or the Function part; they are red herrings.

So let's make it simpler:

Integer i = new Integer(&quot;100&quot;);

That is valid java; i will end up holding the value 100.

It works because... that constructor exists. It is specced to act precisely as Integer.parseInt with a radix of 10 works, and it is deprecated, for 2 good reasons: [A] invoking new Integer() at all, with any value, is deprecated (use Integer.valueOf), and [B] just call parseInt.

答案2

得分: 1

首先,那不是一个方法引用,而是一个 lambda 表达式。

你可能想要做的是 ```Function<String, Integer> f = Integer::parseInt```。

Java 编译器将该 lambda 表达式转换为一个 ```Function``` 对象,其中 ```apply``` 方法被 lambda 内部的内容覆盖。Lambda 表达式基本上是一种语法糖,用于创建只有一个方法的接口(称为函数接口)的实例。实际上,该 lambda 表达式被展开为:

class FunctionImpl extends Function<String, Integer> {
@Override
public Integer apply(String s) {
return new Integer(s); // 它在内部调用了 Integer.parseInt(s)
}
}
Function f = new FunctionImpl();


然而,在实际的字节码中,会生成一个新的方法,并且有一个称为 invokevirtual 的特殊操作码来调用该方法。
英文:

<s>First off, that's not a method reference, it's a lambda.</s>

What you might mean to do is Function&lt;String, Integer&gt; f = Integer::parseInt.

The Java compiler turns that lambda expression into a Function object where the apply method is overriden by what's in the lambda. Lambda expressions are basically syntactic sugar that you use to create instances of interfaces that only have one method (they're called functional interfaces). For all intents and purposes that lambda gets expanded to:

class FunctionImpl extends Function&lt;String, Integer&gt; {
  @Override
  public Integer apply(String s) {
    return new Integer(s); //which calls Integer.parseInt(s) internally
  }
}
Function f = new FunctionImpl();

However, in the actual bytecode, there's a new method generated and a special opcode called invokevirtual that calls that method.</s>

答案3

得分: -1

apply来自Java 8的Function类。

R apply(T t)

将此函数应用于给定的参数。

参数:
t - 函数参数
返回:
函数结果

英文:

apply comes from Java 8's Function class.

> R apply(T t)

> Applies this function to the given argument.

> Parameters:
> t - the function argument
> Returns:
> the function result

huangapple
  • 本文由 发表于 2020年4月8日 06:43:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/61090586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定