logo头像

分享技术,品味人生

Java核心基础之方法引用

Java8带来了很多新特性,这边主要介绍Method References方法引用,让代码更简洁高效!

前言

Method References 俗称方法引用,简化闭包代码,适用于无参场景,下面让我们来看看!

方法引用和闭包的对比

这里我们定义了用户类,包含姓名和生日,并做了简易比较器(未实现comparable接口)

public class TestMethodReference {
    class User{
        String name;
        LocalDate birthday;

        public User(String name, LocalDate birthday) {
            this.name = name;
            this.birthday = birthday;
        }

        public LocalDate getBirthday() {
            return birthday;
        }

        public int compare(User a, User b){
            return a.getBirthday().compareTo(b.getBirthday());
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }

    @Test
    void test1() {
        List<User> userList = Arrays.asList(
                new User("001",LocalDate.of(1980,1,1)),
                new User("002",LocalDate.of(1988,2,1)),
                new User("003",LocalDate.of(1980,1,2))
        );
        userList.stream().sorted(
            //这里采用闭包的调用
                (a,b)->a.getBirthday().compareTo(b.getBirthday())
        ).forEach(System.out::println); //这里采用方法引用
    }
}

通过上面的例子可以看到闭包和方法引用的对比,确实让代码精简了很多!

方法引用的使用场景

适合的场景

当一个 Lambda 表达式调用了一个已存在的方法,可以是静态或非静态的。

不适合的场景

需要传递参数的!如下

XXX demo = () -> ReferenceDemo.commonMethod("Argument in method.");

四种使用方式

静态方法引用

 userList.stream().forEach(System.out::println); //这里调用了System.out下的静态println方法

特定对象的实例方法引用

@Test
void test2() {
    User user = new User("00x", LocalDate.of(1980, 1, 1));
    List<User> userList = Arrays.asList(
        new User("001",LocalDate.of(1980,1,1)),
        new User("002",LocalDate.of(1988,2,1)),
        new User("003",LocalDate.of(1980,1,2))
    );
    userList.stream().sorted(
        user::compare	//这里用了实例对象的内部方法
    ).forEach(System.out::println);
}

//补充,还有两种特殊用法
super::methodName //调用父类方法
this::equals // 等价于lambda的 x->this.equals(x)

特定类的任意方法引用比较难理解

String::toString //对应的 Lambda:(s) -> s.toString(),Lambda 的第一参数成为调用实例方法的对象。

// 例子2,字符串数组中任意一个对象的 compareToIgnoreCase 方法:
String[] stringArray = { "Barbara", "James", "Mary" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

构造方法引用

String::new; //对应的 Lambda:() -> new String()
 

class PersonFactory {
    private Supplier<Person> supplier;

    public PersonFactory(Supplier<Person> supplier) {
        this.supplier = supplier;
    }

    public Person getPerson() {
        return supplier.get();
    }
}

PersonFactory factory = new PersonFactory(Person::new);
Person p1 = factory.getPerson();

絮叨

静态方法引用跟C#的继承很类似,比较难理解的是特定类的方法引用,这推断的方法是比较诡异的,习惯就好了~

评论系统未开启,无法评论!