与lambda的方法参考差异 [英] Method reference difference to lambda

查看:78
本文介绍了与lambda的方法参考差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解到方法参考中有4种类型.但是我不理解" 引用静态方法 "和" 引用特定对象的实例方法"之间的区别输入 ".

例如:

 列表< String>周=新的ArrayList<>();week.add("Monday");week.add(星期二");week.add("Wednesday");week.add(星期四");week.add(星期五");week.add("Saturday");week.add("Sunday");week.stream().map(String :: toUpperCase).forEach(System.out :: println); 

toUpperCase 方法不是不是静态方法,为什么他们可以这种方式而不是这种方式编写

  week.stream().map(s-> s.toUpperCase()).forEach(System.out :: println); 

解决方案

说明

toUpperCase方法不是一个静态方法,为什么他们可以这种方式而不是这种方式编写

  weeks.stream().map(s-> s.toUpperCase()).forEach(System.out :: println); 

方法引用不限于仅限于 static 方法.看看

  .map(String :: toUpperCase) 

它等效于

  .map(s-> s.toUpperCase()) 

Java只会调用您在流中的元素上引用的方法.实际上,这就是参考的全部内容.

官方 Oracle教程对此进行了详细说明


见解,范例

Stream#map 方法(

并且它们都将输出"TEST" ,它们的行为相同.

有关此问题的更多详细信息,请参见Java语言规范JLS§15.13.尤其要看一看本章结尾的例子.

另一个说明,为什么Java甚至不知道 String :: toUpperCase 应该解释为 Function< String,String> ?好吧,总的来说不是.因此,我们始终需要明确指定类型:

 //语句的左侧使编译器很清楚函数<字符串,字符串>toUpper1 =字符串:: toUpperCase;//'map'方法的签名使编译器很清楚.map(String :: toUpperCase) 

还请注意,我们只能使用功能界面:

  @FunctionalInterface公共接口功能< T,R>{...} 


关于 System.out :: println

的说明

由于某些原因,您不会感到困惑

  .forEach(System.out :: println); 

此方法也不 静态.

out 是一个普通的对象实例,而 println PrintStream 的非 static 方法(文档)类.请参阅 System#out 对象文档.

I've learned that there are 4 kinds of types in method reference. But I don't understand the difference between "Reference to a static method" and "Reference to an instance method of an arbitrary object of a particular type".

For example:

  List<String> weeks = new ArrayList<>();
  weeks.add("Monday");
  weeks.add("Tuesday");
  weeks.add("Wednesday");
  weeks.add("Thursday");
  weeks.add("Friday");
  weeks.add("Saturday");
  weeks.add("Sunday");
  weeks.stream().map(String::toUpperCase).forEach(System.out::println);

The method toUpperCase is not a static method why they can write in this way rather than using this way

 weeks.stream().map(s -> s.toUpperCase()).forEach(System.out::println);

解决方案

Explanation

The method toUpperCase is not a static method why they can write in this way rather than using this way

weeks.stream().map(s->s.toUpperCase()).forEach(System.out::println);

Method references are not limited to static methods. Take a look at

.map(String::toUpperCase)

it is equivalent to

.map(s -> s.toUpperCase())

Java will just call the method you have referenced on the elements in the stream. In fact, this is the whole point of references.

The official Oracle tutorial explains this in more detail.


Insights, Examples

The method Stream#map (documentation) has the following signature:

<R> Stream<R> map​(Function<? super T, ? extends R> mapper)

So it expects some Function. In your case this is a Function<String, String> which takes a String, applies some method on it and then returns a String.

Now we take a look at Function (documentation). It has the following method:

R apply​(T t)

Applies this function to the given argument.

This is exactly what you are providing with your method reference. You provide a Function<String, String> that applies the given method reference on all objects. Your apply would look like:

String apply(String t) {
    return t.toUpperCase();
}

And the Lambda expression

.map(s -> s.toUpperCase())

generates the exact same Function with the same apply method.

So what you could do is

Function<String, String> toUpper1 = String::toUpperCase;
Function<String, String> toUpper2 = s -> s.toUpperCase();

System.out.println(toUpper1.apply("test"));
System.out.println(toUpper2.apply("test"));

And they will both output "TEST", they behave the same.

More details on this can be found in the Java Language Specification JLS§15.13. Especially take a look at the examples in the end of the chapter.

Another note, why does Java even know that String::toUpperCase should be interpreted as Function<String, String>? Well, in general it does not. That's why we always need to clearly specify the type:

// The left side of the statement makes it clear to the compiler
Function<String, String> toUpper1 = String::toUpperCase;

// The signature of the 'map' method makes it clear to the compiler
.map(String::toUpperCase)

Also note that we can only do such stuff with functional interfaces:

@FunctionalInterface
public interface Function<T, R> { ... }


Note on System.out::println

For some reason you are not confused by

.forEach(System.out::println);

This method is not static either.

The out is an ordinary object instance and the println is a non static method of the PrintStream (documentation) class. See System#out for the objects documentation.

这篇关于与lambda的方法参考差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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