Java双冒号(::)运算符使用详解
作者:会飞的鱼干干 发布时间:2022-03-31 11:18:17
目录
1.说明
2.先来说下@FunctionalInterface
3. 下面来讲讲这个 "::"是干嘛的
4. 建立一个Person类
4:构建多个person对象,放入数组中,然后对数组中的person重新排序
5:揭秘 "::"符号
6.0 方法引用的支持如下
1.说明
之前没用过::这个东西,今天看flink的时候发现官网有个例子用到了这个符号, 本着求知欲去百度查了一番,没找到能说到我心里去的解释,本着求知欲的态度,我去了官网看了看. java ::
2.先来说下@FunctionalInterface
java8 lambda 内部接口需要@FunctionalInterface这个注解,这个注解是一个说明性质的注解,被@FunctionalInterface注解的接口只能由一个抽象方法,@FunctionalInterface只能用于注解接口而不能用在class以及枚举上.
被@FunctionalInterface注解的符合规则的接口,可以用lambda表达式. 下面举一个例子:
public class Main {
public static void pr(String s){
System.out.println(s);
}
public static void main(String[] args) throws Exception {
List<String> list = Arrays.asList("aaaa", "bbbb", "cccc");
list.forEach(s -> System.out.println(s));
}
}
所以说,@FunctionalInterface用于lambda样式说明.
3. 下面来讲讲这个 "::"是干嘛的
"::"官网对这个符号的解释是方法引用,也就是引用一个方法的意思,英文名称Method References
lambda expressions 可以用来创建一匿名的方法, 这个匿名的方式你需要自己实现.
1. list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
2. list.forEach(s -> System.out.println(s));
上面两种写法是一样的,下面就是lambda表达式.
上面说了lambda表达式你需要自己实现,但是有些时候这不是必要的,比如你的项目里某个地方存在了一个符合当前逻辑的lambda表达式的方法, 那么我是否可以直接拿来用?, 答案是可以, 程序追求的就是不重复极简的思想, 既有则拿来用即可,为什么还要自己实现呢. Method References 就是用来做这件事的.
在看下面的例子之前读者需要知道java 比较器,否则看不懂代码.
4. 建立一个Person类
public class Person implements Comparable<Person>{
public String name;
public int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public static int compareByAge(Person a, Person b) {
return a.compareTo(b);
}
@Override
public int compareTo(Person o) {
if (this.age > o.age){
return -1;
}else{
return 1;
}
}
}
4:构建多个person对象,放入数组中,然后对数组中的person重新排序
public class Test {
//编写Comparator,Person的age
private static final Comparator<Person> COMPARATOR = new Comparator<Person>() {
public int compare(Person a, Person b) {
return a.compareTo(b);//运用User类的compareTo方法比较两个对象
}
};
public static void main(String[] args) {
Person one = new Person("张三",50);
Person two = new Person("李四",100);
ArrayList<Person> array = new ArrayList<>();
array.add(one);
array.add(two);
Collections.sort(array,COMPARATOR);
System.out.println(array);
}
}
//输出结果:
//[Person{name='李四', age=100}
//Person{name='张三', age=50}]
仔细看上面的代码,重点在Collections.sort(array,COMPARATOR);这一行,sort接收两个参数,第一个是要被排序的数组,第二个是一个比较器对象Comparator,其源码如下,我只粘贴了必要的部分.
**@FunctionalInterface**
public interface Comparator<T> {
int compare(T o1, T o2);
}
@FunctionalInterface我们知道,被这个注解修饰的接口可以用lambda表达式的.
所以我们将class Test改成下面的样子:
public class Test {
public static void main(String[] args) {
Person one = new Person("张三",50);
Person two = new Person("李四",100);
ArrayList<Person> array = new ArrayList<>();
array.add(one);
array.add(two);
Collections.sort(array, (a, b) -> a.compareTo(b));
System.out.println(array);
}
}
注意:下面是lambda写法,和正常传统写法
Collections.sort(array, (a, b) -> a.compareTo(b));
和下面的等效
Collections.sort(array, new Comparator() {
@Override
public int compare(Person a, Person b) {
return a.compareTo(b);
}
});
5:揭秘 "::"符号
到这里其实我们上面的功能已经完成了,我们来分析一下代码.
1:构造了两个对象
2:把对象放入了数组
3:Collection.sort(array,Comparator<T>) 对数组进行排序
关键点在于:Comparator<T> 比较器,它是一个被@FunctionalInterface修饰的接口,我们一般成为函数式接口.
因此,Collection.sort(array,Comparator<T>) ,对于第二个参数Comparator<T>,我们可以传入一个匿名实现类,然后实现里面的 int compare(T o1, T o2) 方法,也可以写成lambda表达式的样子,到这里如果你都懂了,那么接下来就好说了,如果没明白,回头接着看,相信自己骚年. 下面我们重点看lambda方式的写法,这和"::"息息相关
Collections.sort(array, (a, b) -> a.compareTo(b));
**(a, b) -> a.compareTo(b)**这个其实就是匿名函数, 该函数的参数分别是Person a, Person b
a.compareTo(b) 是该匿名函数的逻辑,
也即是说我们写出来的这个匿名函数有两个参数,以及一个调用compareTo的函数体,到这里其实结束了,一开始我们就说了,符号"::"的意义就是用一个已经存在的函数代替我们lambda表达式中的函数体,只要这个存在的函数和lambda函数体的函数格式一致就行了. 格式其实就是参数个数,和参数类型下面是新的class Test揭示了答案
public class Test {
public static void main(String[] args) {
Person one = new Person("张三",50);
Person two = new Person("李四",100);
ArrayList<Person> array = new ArrayList<>();
array.add(one);
array.add(two);
Collections.sort(array, Person::compareByAge);//写法一
// Collections.sort(array, one::entyMethod);//写法二
System.out.println(array);
}
}
附官网的一句话:
Because this lambda expression
invokes an existing method,
you can use a method reference
**instead of** a lambda expression
Collections.sort(array, Person::compareByAge);
Collections.sort(array, one::entyMethod);
这两种写法都是可行的.
6.0 方法引用的支持如下
我们上面讲了静态方法,和类方法的代替方式,至于其他的这里不讲了,主要是我要去吃饭了.
来源:https://blog.csdn.net/qq_36066039/article/details/120225882


猜你喜欢
- 最近接了个项目其中有需要要实现此功能:seekbar需要显示最左和最右值,进度要跟随进度块移动。下面通过此图给大家展示下效果,可能比文字描述
- 本文研究的主要是Java编程中的复用类,那么到底复用类是什么东西,又有什么用法,下面具体介绍。看了老罗罗升阳的专访,情不自禁地佩服,很年轻,
- Redis中opsForValue()方法的使用1、set(K key, V value)新增一个字符串类型的值,key是键,value是值
- 首先使用PImage来实例化对象,再通过loadImage赋值,两层for循环遍历图片上的像素点,每隔5个像素点,画一个直径为3的圆。颜色通
- 写在前面:今天用保存QQ账号和密码的实战演练,带大家掌握Android存储中最基本的文件存储方式文件存储是Android中最基本的一种数据存
- 本人在spring中使用redis作为缓存时,遇到两个坑,现在记录如下,算是作为自己的备忘吧,文笔不好,望大家见谅;一、配置文件<!-
- Java中字符串中子串的查找共有四种方法(indexof()) indexOf 方法返回一个整数值,指出 String 对象内子字符串的开始
- 介绍和使用场景1)什么是消息一个事件,需要广播或者单独传递给某个接口2)为什么使用这个配置更新了,但是其他系统不知道是否更新SpringCl
- JAVA枚举,比你想象中还要有用!我经常发现自己在Java中使用枚举来表示某个对象的一组潜在值。在编译时确定类型可以具有什么值的能力是一种强
- C/C++ 左移<<, 右移>>作用1. 左移 <<取两个数字,左移第一个操作数的位,第二个操作数决定要
- createcriteria和or的区别mybatis generator插件生成的example中,有createcriteria和or方
- 最近在用SpringMvc做Http接口时,对方在调用我接口时发现Date格式的默认转化为long,因此在前端页面看到的是一串数字。我们可以
- 就像集成JDBC和其他ORM框架一样,Spring也集成了iBatis。1,配置iBatis客户模板iBatis的核心是com.ibatis
- 介绍Java中的享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存占用和提高性能.Ja
- 前言前几天有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源。我上网收集了一些资料整合了一下,虽然最后这个需求不
- 本文实例为大家分享了PhotoView实现图片双击放大单击退出的具体代码,供大家参考,具体内容如下实现思路1.复制PhotoView&nbs
- 首先不得不提到access_token的分类,一是普通access_token,二是网页授权access_token。其中前者是用于调用微信
- 前言Activity是Android中一个很重要的概念,堪称四大组件之首,关于Activity有很多内容,比如生命周期和启动Flags,这二
- 文件创建:File.Create(Application.StartupPath + "\\AlarmSet.txt")
- 本文实例讲述了Java后台线程操作。分享给大家供大家参考,具体如下:一 点睛有一种线程,它是后面运行的,它的任务是为其他线程提供服务,这种线