【Java8 新特性】Supplier简介

一、Java8新特性,Supplier

1、Supplier简介

supplier接口是JAVA8以后配合lambda表达式和函数式接口编程(FunctionInterface,以下简称FI)组合使用的一个接口,对外表现为双冒号"::",顺便说下"->"符号对应的是Function接口中的Reply方法例如:

Supplier<Person> persionSupplier = Person::new;
Arrays.asList("a","b","c").forEach(e->System.out.println(e));

在Java8中增加的接口Supplier<T>,最适合用于表示工厂。带有Supplier<T>的方法,通常应该限制输入工厂的类型参数使用有限制的通配符类型,以便客户端能够传入一个工厂,来创建指定类型的任意子类型。

应该将这些资源或者工厂传给构造器(或者静态工厂、或者构建器),通过他们来创建类。这个实践就被称做依赖注入,它极大地提高了类的灵活性、可重用性和可测试性。

简而言之,Supplier<T>就是用来创建对象的,相当于new。

2、代码实例

package com.guor.effective.chapter2.java8;

import java.util.function.Supplier;

public class TestSupplier {
    private int age;

    public static void test(){
        System.out.println("Java8新特性,Supplier");
    }

    TestSupplier(){
        System.out.println("构造函数,age,"+age);
    }

    public static void main(String[] args) {
        //创建Supplier容器,声明为TestSupplier类型,此时并不会调用对象的构造方法,即不会创建对象
        Supplier<TestSupplier> sup= TestSupplier::new;
        sup.get().test();
        System.out.println("--------");
        //调用get()方法,此时会调用对象的构造方法,即获得到真正对象
        sup.get();
        //每次get都会调用构造方法,即获取的对象不同
        System.out.println("是否是相同的对象实例"+sup.get()==sup.get().toString());
    }
}

3、控制台输出 

二、Supplier源码分析

Supplier<T>接口源码中只有一个get()方法。

每次get都会调用构造方法,即获取的对象不同。

/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.util.function;

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

可以看到这份代码中,有一个比较奇特的注解@FunctionalInterface,这是一个函数式接口的声明。该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。

三、lambda表达式与Supplier的组合使用

为何不直接使用new?而使用Supplier,感觉华而不实,和new有啥区别?

1、person类

package com.guor.effective.chapter2.java8;

public class Person {
    Integer id;
    String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Person() {
        this.name="mike";
        System.out.println("创建了一个对象");
    }
    public Person(Integer x,String y) {
        this.id = x;
        this.name=y;
    }
}

2、测试类 

package com.guor.effective.chapter2.java8;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TestSupplier1 {
    public static void main(String[] args) {
        List<Person> list = new ArrayList();
        list.add(new Person(1, "guor"));
        list.add(new Person(2, "xiaoxia"));
        list.add(new Person(3, "xiaotong"));
        Map<Integer, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));
        System.out.println(map);
  }
}

3、控制台输出 

 四、总结

Supplier单独的使用并没有什么意义,但是如果要使用JAVA8的其他新特性例如lambda表达式,Function,stream,Collectors等则需要花点时间看一下,否则会发现同样是JAVA为啥他写的像外星文,我写的像是幼儿园的这种闹剧。

前一篇:【Java8 新特性】函数式接口 + Lamda表达式推导过程

后一篇:【Java8 新特性】Lambda表达式总结(全栈最强,绝对豪横)

猜你喜欢

转载自blog.csdn.net/guorui_java/article/details/108009650