java8新特性之方法引用

java8方法引用有四种形式:

  • 静态方法引用       :   ClassName :: staticMethodName
  • 构造器引用        :   ClassName :: new
  • 类的任意对象的实例方法引用:   ClassName :: instanceMethodName
  • 特定对象的实例方法引用  :   object :: instanceMethodName

 

lambda表达式可用方法引用代替的场景可以简要概括为:lambda表达式的主体仅包含一个表达式,且该表达式仅调用了一个已经存在的方法。方法引用的通用特性方法引用所使用方法的入参和返回值与lambda表达式实现的函数式接口的入参和返回值一致


静态方法引用

静态方法引用的语法格式为: 类名::静态方法名 ,如
System.out::println 等价于lambda表达式 s -> System.out.println(s) ,代码示例:

public class Test
{
    public static void main(String[] args)
    {
        //lambda表达式使用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> Test.println(s));
        //静态方法引用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(Test::println);
    }
    
    public static void println(String s)
    {
        System.out.println(s);
    }
}

静态方法引用适用于lambda表达式主体中仅仅调用了某个类的静态方法的情形

 

构造器引用

构造器引用的语法格式为: 类名::new ,如() -> new ArrayList<String>() 等价于 ArrayList<String>::new,代码示例:

Supplier<List<String>> supplier1= () -> new  ArrayList<String>();

等价于

Supplier<List<String>> supplier = ArrayList<String>::new;

构造器引用适用于lambda表达式主体中仅仅调用了某个类的构造函数返回实例的场景

 

类的任意对象的实例方法引用

类的任意对象的实例方法引用的语法格式为: 类名::实例方法名 , 这种方法引用相对比较复杂,我们来看示例:

一、示例1

  Arrays.sort(strs,(s1,s2)->s1.compareToIgnoreCase(s2));

等价于

  Arrays.sort(strs, String::compareToIgnoreCase);

上述示例中,strs为一个String数组,lambda表达式(s1,s2)->s1.compareToIgnoreCase(s2)实现函数式接口的是Comparator接口, 我们看下jdk8中Comparator接口的源码(截取部分):

  @FunctionalInterface
  public interface Comparator<T> {
      int compare(T o1, T o2);
  }

而String类的compareToIgnoreCase方法源码为:

    public int compareToIgnoreCase(String str) {
        return CASE_INSENSITIVE_ORDER.compare(this, str);
    }

可以发现函数式接口Comparator<String>的compare方法比String类的compareToIgnoreCase方法多了一个String类型的入参。看到这里对类的任意对象的实例方法引用的使用可能似懂非懂,下面我们看一个自己实现一个类的任意对象的实例方法引用的示例(示例2)。

二、示例2

public class Student
{
    
    private String name;
    
    private Integer score;
    
    public void setNameAndScore(String name, Integer score)
    {
        this.name = name;
        this.score = score;
        System.out.println("Student "+  name +"'s score is " + score);
    }
     
    public static void main(String[] args)
    {
        /*lambda表达式的用法:
        TestInterface testInterface = (student, name, score) -> student.setNameAndScore(name, score);*/
        //类的任意对象的实例方法引用的用法:
        TestInterface testInterface = Student::setNameAndScore;
        testInterface.set(new Student(), "DoubleBin", 100);
    }
    
    @FunctionalInterface
    interface TestInterface
    {
        // 注意:入参比Student类的setNameAndScore方法多1个Student对象,除第一个外其它入参类型一致
        public void set(Student d, String name, Integer score);
    }
}

看完上述代码,我们可以总结出类的任意对象的实例方法引用的特性为:

  • 1、方法引用的通用特性:方法引用所使用方法的入参和返回值与lambda表达式实现的函数式接口的入参和返回值一致;
  • 2、lambda表达式的第一个入参为实例方法的调用者,后面的入参与实例方法的入参一致

 

特定对象的实例方法引用

特定对象的实例方法引用的语法格式为: 对象::实例方法名 , 示例代码:

public class Test
{
    public static void main(String[] args)
    {
        Test test = new Test();
        // lambda表达式使用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(s -> test.println(s));
        // 特定对象的实例方法引用:
        Arrays.asList(new String[] {"a", "c", "b"}).stream().forEach(test::println);
    }
    
    public void println(String s)
    {
        System.out.println(s);
    }
}

特定对象的实例方法引用适用于lambda表达式的主体中仅仅调用了某个对象的某个实例方法的场景

 

总结

方法引用使用运算符::连接类(或对象)与方法名称(或new)实现在特定场景下lambda表达式的简化表示,使用时要注意方法引用的使用场景及各种方法引用的特性。使用方法引用的好处是能够更进一步简化代码编写,使代码更简洁。
然而作者认为,方法引用代替lambda表达式对代码的简化程度远远没有lambda表达式代替匿名类的简化程度大, 有时反而增加了代码的理解难度(如2.3节:类的任意对象的实例方法引用),且使用场景的局限性不利于增加或修改代码,个人认为有时没有必要刻意使用方法引用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值