什么是Supplier

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

Arrays.asList("a","b","c").forEach(e->System.out.println(e));

其中的双冒号点击进去就是这个Supplier接口:package java.util.function;

/**

* Represents a supplier of results.

*

*

There is no requirement that a new or distinct result be returned each

* time the supplier is invoked.

*

*

This is a functional interface

* whose functional method is {@link #get()}.

*

* @param the type of results supplied by this supplier

*

* @since 1.8

*/

@FunctionalInterface

public interface Supplier {

/**

* Gets a result.

*

* @return a result

*/

T get();

}

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

Supplier的使用

我们可以从源代码中看出来,Supplier接口中只有一个方法,就是一个get方法且无需参数,返回的是泛型T。一般的类强制转换为一个接口编译器(eclipse)不会报错但是运行时会报错。假设现在我们新建一个普通类Person: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) {

// TODO Auto-generated constructor stub

this.id = x;

this.name=y;

}

// public String toString() {

// return this.name;

// }

}

Person类中只有基本的属性与get/set方法,最最常见的对象创建方法就是直接一个new,这是正确的我们也恰好使用的是这个特性Person::new

在编译器中这句代码相当于声明一个Person类型的Supplier,返回一个Supplier接口,接下来是重点:使用get方法会执行Person类的无参构造方法,每一次使用get方法都会新建一个对象,所以不是Supplier保存了Person对象,而是需要使用时创建一个,在main中运行以下代码:Supplier persionSupplier = Person::new;

System.out.println("-------------分割线-------------");

System.out.println("supplier中的实体类地址为:"+persionSupplier.get().toString());

persionSupplier.get().setName("coda");

System.out.println("更改后supplier中的实体类地址为:"+persionSupplier.get().toString());

而输出的结果为:

-------------分割线-------------

创建了一个对象

supplier中的实体类地址为:Person@87aac27

创建了一个对象

创建了一个对象

更改后supplier中的实体类地址为:Person@3e3abc88

可以得知:

第一句代码并没有调用构造方法

第三句代码调用了构造方法所以给出了地址 87aac27

第四句代码也调用了构造方法所以他其实已经不是上面的那个地址为87aac27的Person对象而是一个新的对象了

第五句代码也调用了构造方法所以他是一个全新的对象,地址为:3e3abc88

lambda表达式与Supplier的组合使用

看了以上的同学可能会问,至于吗,我只是想新建一个对象而已,我一个new就能解决的事需要搞这么多花里花俏的?

冷静老哥。JAVA8说了是扩展对象的用法,而不是替代传统的new方式,以下贴代码,注释不需要管,但是也是个学习的东西所以顺便贴上去了,可以解除注释试一下输出:List list = new ArrayList();

list.add(new Person(1, "haha"));

list.add(new Person(2, "rere"));

list.add(new Person(3, "fefe"));

//Map mapp = list.stream().collect(Collectors.toMap(Person::getId, Function.identity()));

//Map mapp = list.stream().collect(Collectors.toMap(x -> x.getId(), x->x));

//System.out.println(mapp);

Map map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));

//Map map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(x1,x2)->x1));

以下的功能很简单,把list中的三个Person对象变成一个Map。Map是一个K-V形式的集合,他要求key不可以重复,所以当我们把Person中的构造方法的123改成相同的那就会出现报错,注意下面那句注释(x1,x2)->x1意味着当第一个和第二个参数的key一致时选用第一个元素,这样即算有两个相同的KEY也不会影响到代码的运行,->是什么我会在另外一篇博文中详细介绍,现在我们只关心::,也就是Supplier在这段代码中起什么作用。Person::getId, Person::getName这句话到底是什么意思,这个我们直接看map的输出就好:

{1=haha, 2=rere, 3=fefe}

看到这个结果我们就知道了Person::getId指的是使用Person对象中的ID作为键,使用Person::getName作为Map中元素的值,getId,getName指的是list中的元素使用的方法名字。虽然可能这段代码还是太过于复杂但是这是我觉得比较适合用来诠释JAVA8的操作拓展改变的所以想了一下还是用的这个例子。

总结

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

supplier java8_关于JAVA8中关于Supplier的个人理解相关推荐

  1. Java8中的函数式接口Supplier、Consumer、BiConsumer详解

    目录 一.什么是函数式接口? 二.函数式接口应用实战 1. BiConsumer接口和Consumer接口 1) accept(T t,U u)方法 2) andThen(BiConsumer)方法 ...

  2. java supplier t_在Java中如何使用lambda表达式中的Supplier T接口?

    Supplier接口是一个预定义的接口,表示结果的提供者.它是使用lambda表达式.方法引用或默认构造函数实例化的.Supplier接口的函数方法是get()方法.此接口属于java.util.fu ...

  3. 【Java8新特性】面试官问我:Java8中创建Stream流有哪几种方式?

    写在前面 先说点题外话:不少读者工作几年后,仍然在使用Java7之前版本的方法,对于Java8版本的新特性,甚至是Java7的新特性几乎没有接触过.真心想对这些读者说:你真的需要了解下Java8甚至以 ...

  4. 教你怎么样在 Java8 中优雅的避开空指针异常

    2019独角兽企业重金招聘Python工程师标准>>> 要说 Java 编程中哪个异常是你印象最深刻的,那 NullPointerException 空指针可以说是臭名昭著的.不要说 ...

  5. java8中的Lamba表达式

    1.什么情况有下可以使用lamba 在函数式接口中可以使用 2.什么是函数式接口 只有一个抽象方法的接口称为函数式接口,同时将这个抽象方法称为函数描述符 3.java8中新增了哪些函数式接口 Pred ...

  6. Function接口 – Java8中java.util.function包下的函数式接口

    作者:   Mohamed Sanaulla  译者: 李璟(jlee381344197@gmail.com) 早先我写了一篇<函数式接口>,探讨了Java8中函数式接口的用法.如果你正在 ...

  7. java8中class怎么用_Java8中你可能不知道的一些地方之方法引用实战

    Java8 中引入方法引用新特性,用于简化应用对象方法的调用, 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法. 方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的 ...

  8. java8中的lambda表达式实用详解

    java8中的lambda表达式实用详解 1. lambda简介 ​ Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中 ...

  9. Java8中Collector详解及自定义Collector

    文章目录 1.Collector介绍 2.Collector约束 3.Collector接口方法 4.理解Collector接口声明的方法 5.整合自定义Collector 6.使用collect方法 ...

最新文章

  1. c#之旅--第六天(类,对象,方法)
  2. centos7 中iptables、firewalld 、netfilter 关系
  3. 机器学习中的数学(4)-线性判别分析(LDA), 主成分分析(PCA)
  4. bash-shell--高级编程
  5. 从比特币脚本引擎到以太坊虚拟机
  6. 传统公司部署OpenStack(t版)简易介绍(二)——Keystone组件部署
  7. html 二级试题,计算机二级考试WEB试题及答案
  8. 【WP主题】仿下载吧全开源无加密wordpress主题模板内含newzhan2.60无授权版本
  9. php td生成excel 斜杠表头_邮件合并功能都不掌握,还怎么成为Excel达人?
  10. 把windows当linux用,把Windows Vista当成Linux系统来使用
  11. REX-Ray 了解
  12. Socket API: setsockopt(), recvmsg(), sendmsg()函数
  13. 基于C/C++的弹出气泡框
  14. email邮箱格式校验
  15. 我们一起追逐过的大肥猫——tomcat部署
  16. 流量卡物联网卡管理平台源码|PHP管理系统源码 成品可商用系统
  17. cocos2d-x精灵的放大和缩小
  18. 《从0到1:CTFer成长之路》SQL注入-2
  19. iOS 判断手机型号及系统版本(最新)持续更新
  20. 昆明等保合规怎么建设,企业等保安全解决方案,等保建设测评流程

热门文章

  1. 复杂任务处理三部曲:系统性思维、结构化思维、流程化管理
  2. <Zhuuu_ZZ>HIVE(十一)函数
  3. 解决PanDownload登录提示账号登录失败,获取bdstoken失败问题
  4. gif透明背景动画_iPad Procreate入门笔记03 - GIF动画制作
  5. sinx的导数是多少
  6. 4、假想目标.PHONY
  7. 频繁跳槽是否能够快速升职呢?
  8. 程序员修炼之道(跨年阅读)-----精彩---经典---(待整理)
  9. Auto reloading enabled
  10. 如何运行第一个C|C++语言程序