时间:2021-05-19
本文为个人理解,不保证完全正确。
官方文档中将双冒号的用法分为4类,按照我的个人理解可以分成2类来使用。
官方文档
官方文档中将双冒号的用法分为了以下4类:
用法 举例 引用静态方法 ContainingClass::staticMethodName 引用特定对象的实例方法 containingObject::instanceMethodName 引用特定类型的任意对象的实例方法 ContainingType::methodName 引用构造函数 ClassName::new
以下是我的理解
个人理解
双冒号的作用
在使用双冒号前我们要先搞清楚一个问题:为什么要使用双冒号?也就是双冒号的作用是什么。
双冒号的设计初衷是为了化简Lambda表达式,不熟悉Lambda表达式的同学可以先了解一下。
Lambda表达式的形式有两种:
包含单独表达式 :parameters -> an expression
list.forEach(item -> System.out.println(item));包含代码块:parameters -> { expressions }
list.forEach(item -> { int numA = item.getNumA(); int numB = item.getNumB(); System.out.println(numA + numB);});使用双冒号可以省略第一种Lambda表达式中的参数部分,即item ->和调用方法的参数这两部分。
例如:
双冒号的使用条件
使用双冒号有两个条件:
条件1
条件1为必要条件,必须要满足这个条件才能使用双冒号。
Lambda表达式内部只有一条表达式(第一种Lambda表达式),并且这个表达式只是调用已经存在的方法,不做其他的操作。
条件2
由于双冒号是为了省略item ->这一部分,所以条件2是需要满足不需要写参数item也知道如何使用item的情况。
有两种情况可以满足这个要求,这就是我将双冒号的使用分为2类的依据。
情况 举例 Lambda表达式的参数与调用函数的参数完全一致 list.forEach(item -> System.out.println(item)) 调用的函数是参数item对象的方法且没有参数 list.stream().map(item -> item.getId())
一些栗子
Lambda表达式的参数与调用函数的参数完全一致时
静态方法调用
非静态方法调用
调用构造方法
官方给出的例子
先定义一个方法,这个方法的作用是将一个集合的内容复制到另一个集合
public <T, SOURCE extends Collection<T>, DEST extends Collection<T>>DEST transferElements(SOURCE sourceCollection, Supplier<DEST> collectionFactory) { DEST result = collectionFactory.get(); result.addAll(sourceCollection); return result;}调用这个方法
//化简前Set<Person> rosterSetLambda = transferElements(roster, () -> new HashSet<>());//化简后Set<Person> rosterSet = transferElements(roster, HashSet::new);稍微解释一下:
调用时传入的Lambda表达式相当于是对Supplier的继承,并重写Supplier的get()方法,下面是Supplier的源码:
@FunctionalInterfacepublic interface Supplier<T> { /** * Gets a result. * * @return a result */ T get();}在transferElements()方法中调用collectionFactory.get()时相当于调用重写后的方法{return new HashSet<>();}
我自己写的一个例子
第一个类:
@Datapublic class ModelA { private String id; public ModelA(String id) { this.id = id; } public ModelA() { }}第二个类
class ClassB { private final List<ModelA> list = new ArrayList<>(); public void add(String string, Function<String, ModelA> function) { list.add(function.apply(string)); }}测试代码
ClassB classB = new ClassB();d//化简前classB.add("ddd", item -> new ModelA(item));//化简后classB.add("ddd", ModelA::new);调用的函数是参数item对象的方法且没有参数时
一种特殊情况
除了上述两种情况可以使用双冒号化简Lambda表达式外,还存在一种特殊情况也可以使用双冒号。
当Lambda表达式的参数有两个(形如(a,b) -> an expression)时,调用a的方法参数为b时,例如:
到此这篇关于浅谈对Java双冒号::的理解的文章就介绍到这了,更多相关Java双冒号::内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
浅谈鼠标参数对操作的影响(图3)DPI已经大大地落伍。为什么还有少数职业选手继续运用? 浅谈鼠标参数对操作的影响(图4) 浅谈鼠标参数对操作的影响(图5
这篇文章的目的在于介绍Java泛型,使大家对Java泛型的各个方面有一个最终的,清晰的,准确的理解,同时也为下一篇《重新理解Java反射》打下基础。简介泛型是J
浅谈java执行jar包中的main方法通过OneJar或Maven打包后jar文件,用命令:java-jar****.jar执行后总是运行指定的主方法,如果j
浅谈java内存模型不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安
在项目中遇到try...catch...语句,因为对Java异常处理机制的流程不是很清楚,导致对相关逻辑代码不理解。所以现在来总结Java异常处理机制的处理流程