无法从静态上下文中引用非静态方法_学习编程|Java攻略读书笔记-Lambda表达式与方法引用...

作者:小犀利
链接:https://www.nowcoder.com/discuss/132415
来源:牛客网

lambda与方法引用

  • 如果说lambda表示式本质上是将方法作为对象进行处理,那么方法引用就是将现有方法作为lambda表达式进行处理
  • 我们首先来看下面这个例子
import java.util.function.Consumer; 
import java.util.stream.Stream; 
public class Test01 {
     public static void main(String[] args) {
        // 使用lambda表达式,将流的所有元素打印到标准输出 
        Stream.of(3, 1, 4, 1, 5, 9).forEach(x -> System.out.println(x)); 
        // 使用方法引用的方式,将流的所有元素打印到标准输出 
        // 双冒号表示法在system.out实例上提供了对println方法的引用,属于PrintStream类型的引用。方法引用的末尾无需括号 
        Stream.of(3, 1, 4, 1, 5, 9).forEach(System.out::println); 
        // 将方法引用赋给函数式接口,将流的所有元素打印到标准输出 
        Consumer<Integer> printer = System.out::println;
        Stream.of(3, 1, 4, 1, 5, 9).forEach(printer); 
        // 在静态方法中使用方法引用 
        Stream.generate(Math::random)        // 静态方法 
                .limit(10).forEach(System.out::println);        // 实例方法 
    }
}
  • 与lambda语法相比,方法引用具有以下2个优点,使得代码更易于阅读
    • 首先,方法引用往往更短
    • 其次,方法引用通常包括含有该方法的类的名称

语法

方法引用包括以下三种方式

  • object::instanceMethod
    • 引用特定对象的实例方法,如System.out::println
  • Class::staticMethod
    • 引用静态方法,如:Math::max
  • Class::instanceMethod
    • 调用特定类型的任意对象的实例方法,如String::length

lambda表达式和方法引用在任何情况下都不能脱离上下文存在,有时候为避免歧义,经常在方法引用的左侧使用this或super

  • 以对象引用为例,上下文提供了方法的参数;对于System.out::println,等效的lambda表达式为:
    • //相当于System.out::println
    • x -> System.out.println(x);
    • 上下文提供了x的值,它被用作方法的参数
  • 静态方法max与之类似
    • //相当于Math::max
    • (x,y)->Math.max(x,y)
    • 此时,需要上下文提供两个参数,lambda表达式返回较大的数
  • 通过类名调用实例方法,等效的lambda表达式为:
    • //相当于String::length
    • x -> x.length()
    • 此时上下文提供x的值,用作方法的目标而非参数

如果通过类名引用一个传入多个参数的方法,则上下文提供的第一个元素将作为方法的目标,其他元素作为方法的参数

import java.util.Arrays; 
import java.util.List; 
import java.util.stream.Collectors; 
/**
 * Stream接口定义的sorted方法传入Comparator<T>作为参数 其单一抽象方法为int compare(String other)
 * sorted方法将每对字符串提供给比较器,并提供返回整数的符号对它们进行排序 
*/ 
public class Test02 { 
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("this", "is", "a", "list", "of", "strings");

        List<String> sorted1 = strings.stream()
                .sorted((s1, s2) -> s1.compareTo(s2))
        // 调用第一个参数s1的compareTo方法,并使用第二个元素s2作为该方法的参数 
                .collect(Collectors.toList());

        List<String> sorted2 = strings.stream()
                .sorted(String::compareTo)
                .collect(Collectors.toList());
    }
}
  • 在流处理中,如果需要处理一系列的输入,则会频繁的使用方法引用中的类名来访问实例方法,如下例子
import java.util.stream.Stream; 
/**
 * 程序调用length方法并将每个字符串转换成一个整数打印出来 
*/ 
public class Test03 { public static void main(String[] args) {
        Stream.of("this", "is", "a", "list", "of", "strings")
                .map(String::length)// 通过类名访问实例方法 
                .forEach(System.out::println);
                // 通过对象引用访问实例方法  
                //等效的lambda表示式 
        Stream.of("this", "is", "a", "list", "of", "strings")
                .map(s -> s.length())
                .forEach(x -> System.out.println(x));

    }
}

与作者交流:https://www.nowcoder.com/discuss/132415

更多笔经面经:https://www.nowcoder.com/discuss?order=0&type=2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值