jdk8的新特性有很多,最亮眼的当属函数式编程的语法糖,本文主要讲解下双冒号::的用法。

概念

类名::方法名,相当于对这个方法闭包的引用,类似js中的一个function。比如:

Function<String,String> func =  String::toUpperCase;

(Function在java.util.function包下,也是jdk8新加入的类,同级目录下有很多函数式编程模型接口,比如Consumer/Predicate/Operator等)

func相当于一个入参和出参都为String的函数,可以直接

func.apply("abc")

接收一个参数,返回一个结果("ABC")。也可以用于代替下面的Lambda表达式:

List<String> l = Arrays.asList("a","b","c");
l.stream().map(s -> s.toUpperCase());
l.stream().map(func);

下面自定义一个函数式接口

public class MyConsumer<String> implements Consumer<String> {
    @Override
    public void accept(String s) {
        System.out.println(s);
    }
}

下面这俩种写法等价:

List<String> l = Arrays.asList("a","b","c");

l.forEach(new MyConsumer<>());
l.forEach(s -> System.out.println(s));

但是,这种写法却不行,编译失败:

l.forEach(MyConsumer::accept);

因为MyConsumer的accept方法不是静态的,如果想使用这个方法,需要一个实例,还需要一个入参,共俩个参数。而List.forEach中需要的是consumer类型,相当于s -> {...},只有一个参数。

下面详细分析双冒号使用的各种情况

新建一个类,里面声明四个代表各种情况的方法:

public class DoubleColon {

    public static void printStr(String str) {
        System.out.println("printStr : " + str);
    }     public void toUpper(){
        System.out.println("toUpper : " + this.toString());
    }     public void toLower(String str){
        System.out.println("toLower : " + str);
    }     public int toInt(String str){
        System.out.println("toInt : " + str);
        return 1;
    }
}

把它们用::提取为函数,再使用:

Consumer<String> printStrConsumer = DoubleColon::printStr;
printStrConsumer.accept("printStrConsumer"); Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;
toUpperConsumer.accept(new DoubleColon()); BiConsumer<DoubleColon,String> toLowerConsumer = DoubleColon::toLower;
toLowerConsumer.accept(new DoubleColon(),"toLowerConsumer"); BiFunction<DoubleColon,String,Integer> toIntFunction = DoubleColon::toInt;
int i = toIntFunction.apply(new DoubleColon(),"toInt");

非静态方法的第一个参数为被调用的对象,后面是入参。静态方法因为jvm已有对象,直接接收入参。

再写一个方法使用提取出来的函数:

public class TestBiConsumer {
    public void test(BiConsumer<DoubleColon,String> consumer){
        System.out.println("do something ...");
    }
}

下面这俩种传入的函数是一样的:

TestBiConsumer obj = new TestBiConsumer();
obj.test((x,y) -> System.out.println("do something ..."));
obj.test(DoubleColon::toLower);

总结

用::提取的函数,最主要的区别在于静态与非静态方法,非静态方法比静态方法多一个参数,就是被调用的实例。

jdk8新特性之双冒号 :: 用法及详解的更多相关文章

  1. Java 8新特性探究(五)Base64详解

    BASE64 编码是一种常用的字符编码,在很多地方都会用到.但base64不是安全领域下的加密解密算法.能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使 ...

  2. ES6新特性三: Generator(生成器)函数详解

    本文实例讲述了ES6新特性三: Generator(生成器)函数.分享给大家供大家参考,具体如下: 1. 简介 ① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改 ...

  3. Servlet3.0新特性WebFilter(Annotation Filter)详解

    摘要: Servlet3.0作为J2EE 6规范一部分,并随J2EE6一起发布,WeFilter是过滤器注解,是Servlet3.0的新特性,不需要在web.xml进行配置,简化了配置. Name T ...

  4. Java 8新特性探究(十一)Base64详解

    开发十年,就只剩下这套架构体系了! >>>   BASE64 编码是一种常用的字符编码,在很多地方都会用到.但base64不是安全领域下的加密解密算法.能起到安全作用的效果很差,而且 ...

  5. jdk8新特性表达式1

    Jdk8中有好多新的特性,比如引入Lambda,简化代码的书写等等 我们先看一个关于Lambda的使用 /*** 输出list */@Testpublic void test() { String[] ...

  6. jdk8新特性-stream

    一.什么是流stream 1.可理解为高级版本的 Iterator 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的. 2.单向,不可往复 数据只能遍历一次,遍历过一次后即用尽了,就好比 ...

  7. 一次电话Java面试的问题总结(JDK8新特性、哈希冲突、HashMap原理、线程安全、Linux查询命令、Hadoop节点)

    面试涉及问题含有: Java JDK8新特性 集合(哈希冲突.HashMap的原理.自动排序的集合TreeSet) 多线程安全问题 String和StringBuffer JVM 原理.运行流程.内部 ...

  8. JDK8新特性关于Stream流

    在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: 1 2 3 ...

  9. java进阶一之jdk8新特性

    1.官方发布的jdk8新特性 2.51CTO相关专题

随机推荐

  1. JavaScript 递归法排列组合二维数组2

    <html> <head> <title>二维数组排列组合</title> </head> <body> <div id= ...

  2. js和.net后台交互

    1.asp.net呼叫js                        Response.Write("<script language=javascript>"); ...

  3. java反射机制的简单介绍

    参考博客: https://blog.csdn.net/mlc1218559742/article/details/52754310 先给出反射机制中常用的几个方法: Class.forName (& ...

  4. CSS的BFC和hasLayout及其应用场景

    前端精选文摘:BFC 神奇背后的原理 一.BFC是什么? 先介绍 Box.Formatting Context的概念. Box: CSS布局的基本单位 Box 是 CSS 布局的对象和基本单位, 直观 ...

  5. SQL Server ->> SQL Server 2016功能改进之 -- Update Statistics

    1) 以前SQL Server更新一张表/索引的间隔是固定的,创建时更新一次,到了500行时更新第二次,接下来就是呈百分比式的间隔去更新,距离数据修改量达到表的行数量的的20%再次触发更新.但是这样的 ...

  6. Day03——Python函数

    函数定义和使用 1.语法 def 函数名(参数): ... 函数体 ... 返回值 函数的定义主要有如下要点: def:表示函数的关键字 函数名:函数的名称,日后根据函数名调用函数 函数体:函数中进行 ...

  7. 如何向数据库中添加TIMESTAMP(6)类型的数据

    to_timestamp('2011-11-11 11:11:11.1','yyyy-mm-dd hh24:mi:ss.ff')

  8. Markdown学习使用

    本文记录Markdown的基础应用. 一.基础知识 Markdown 是一种标记语言 文件后缀名:.md 编辑工具:VSCode(visual studio code) VSCode中预览模式快捷键: ...

  9. My SQL 和SQL Server区别

    MySQL 与SQL Server区别 今天了解了二者区别,整理网上查阅资料,总结列举如下: MSSQL == SQL server 是sybase与微软合作时期的产物. 对于程序开发人员而言,目前使 ...

  10. 全文检索及ElasticSearch框架学习

    1.   全文检索的通用步骤: 1.建库步骤: a 分词 b 倒排索引   :  关键词和记录Id的对应关系,1对多. 2.查询步骤: a 分词 b 查索引 c 取交集或并集 2.    产品使用全文 ...