Java里的引用详解

1.体验方法引用

  • 方法引用的出现原因

    在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作

    那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑呢?答案肯定是没有必要

    那我们又是如何使用已经存在的方案的呢?

    这就是我们要讲解的方法引用,我们是通过方法引用来使用已经存在的方案

package yingyong;import java.util.Arrays;
import java.util.Comparator;public class demo1 {public static void main(String[] args) {//需求:创建一个数组,进行倒序排列Integer[] arr = {3, 5, 4, 1, 6, 2};//匿名内部类Arrays.sort(arr, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});//lambda表达式//因为第二个参数的类型Comparator是一个函数式接口Arrays.sort(arr, (Integer o1, Integer o2)-> {return o2 - o1;});//lambda表达式简化格式Arrays.sort(arr, ( o1,  o2)-> o2 - o1);//方法引用//1.引用处需要是函数式接口//2.被引用的方法需要已经存在//3.被引用方法的形参和返回值需要跟抽象方法的形参和返回值保持一致//4.被引用方法的功能需要满足当前的要求Arrays.sort(arr,demo1::mySort);//表示引用demo1类里面的mySort方法//把这个方法当做抽象方法的方法体}public static int mySort(int o1, int o2) {return o2 - o1;}
}

2.方法引用符

  • 方法引用符

    :: 该符号为引用运算符,而它所在的表达式被称为方法引用

  • 推导与省略

    • 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导

    • 如果使用方法引用,也是同样可以根据上下文进行推导

    • 方法引用是Lambda的孪生兄弟

3.引用类方法

引用类方法,其实就是引用类的静态方法

  • 格式

    类名::静态方法

  • 范例

    Integer::parseInt

    Integer类的方法:public static int parseInt(String s) 将此String转换为int类型数据

  • 练习描述

    • 定义一个接口(Converter),里面定义一个抽象方法 int convert(String s);

    • 定义一个测试类(ConverterDemo),在测试类中提供两个方法

      • 一个方法是:useConverter(Converter c)

      • 一个方法是主方法,在主方法中调用useConverter方法

package yingyong;import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;public class demo2 {public static void main(String[] args) {/*需求:集合里一下的数字,把他们变成Int类型"1","2","3","4","5"*///1.常规方法ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "1", "2", "3", "4", "5");ArrayList<Integer> list2 = new ArrayList<>();for (String s : list1) {int i = Integer.parseInt(s);list2.add(i);}System.out.println(list2);System.out.println("---------------");//2.stream流list1.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {int i = Integer.parseInt(s);return i;}}).forEach(s-> System.out.println(s));System.out.println("---------------");//简化lambda表达式list1.stream().map( s-> Integer.parseInt(s)).forEach(s-> System.out.println(s));System.out.println("---------------");//3.引用类方法list1.stream().map(Integer::parseInt).forEach(s-> System.out.println(s));}
}
  • 使用说明

    Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数

4.引用对象的实例方法

引用其他类的成员方法

package yingyong;import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;/*方法引用(引用成员方法)格式其他类:其他类对象::方法名本类:this::方法名(引用处不能是静态方法)父类:super::方法名(引用处不能是静态方法)需求:集合中有一些名字,按照要求过滤数据数据:"张无忌","周芷若","赵敏","张强","张三丰"要求:只要以张开头,而且名字是3个字的*/
public class demo3 {public static void main(String[] args) {//1.创建集合ArrayList<String> list = new ArrayList<>();//2.添加数据Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");//1.stream()流方法//  要求:只要以张开头,而且名字是3个字的list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));//引用类方法  ---其他类list.stream().filter(new Predicate<String>() {@Overridepublic boolean test(String s) {return s.startsWith("张") && s.length() == 3;}}).forEach(s -> System.out.println(s));System.out.println("-----------------");//我们现在就在其他类自己写一个这个接口的实现类方法// 其他类:其他类对象::方法名list.stream().filter(new Mytest()::test).forEach(s -> System.out.println(s));}
}

package yingyong;public class Mytest {public boolean test(String s) {return   s.startsWith("张") && s.length()==3;}
}

引用本类成员方法:this::方法名(引用处不能是静态方法)

public class demo4 {public static void main(String[] args) {new test();}}
package yingyong;import java.util.ArrayList;
import java.util.function.Predicate;public class test {public test(){method01();}private void method01() {//创建集合 初始化集合数据ArrayList<Integer> list = new ArrayList<>();for (int i = 0; i < 10; i++) {list.add(i);}//调用方法过滤奇数的数字method02(list);}private void method02(ArrayList<Integer> list) {list.stream().filter(this::fun).forEach(s->System.out.println(s));}public boolean fun(int i) {return i % 2 == 0;}
}

5.引用构造器

为他专门写一个构造方法 

public class Student {private String name;private int age;public Student() {}public Student(String str) {String[] arr = str.split(",");this.name = arr[0];this.age = Integer.parseInt(arr[1]);}public Student(String name, int age) {this.name = name;this.age = age;}
}
package yingyong;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*方法引用(引用构造方法)格式类名::new目的:创建这个类的对象需求:集合里面存储姓名和年龄,要求封装成Student对象并收集到List集合中方法引用的规则:1.需要有函数式接口2.被引用的方法必须已经存在3.被引用方法的形参和返回值,需要跟抽象方法的形参返回值保持一致4.被引用方法的功能需要满足当前的需求*/
public class demo5 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张三,18", "李四,22", "王五,25");//1.匿名内部类方法list.stream().map(new Function<String, Student>() {@Overridepublic Student apply(String s) {String name = s.split(",")[0];int age = Integer.parseInt(s.split(",")[1]);return new Student(name, age);}}).forEach(s -> System.out.println(s));System.out.println("---------------");//2.lambda方法list.stream().map(s-> new Student(s.split(",")[0],Integer.parseInt(s.split(",")[1]))).forEach(s -> System.out.println(s));System.out.println("---------------");// 3.方法引用(引用构造方法)/*  格式类名::new*/List<Student> newlist = list.stream().map(Student::new).collect(Collectors.toList());System.out.println(newlist);}
}

6.类名引用成员方法

源码里的String里的把字符串变大写的方法 

    public String toUpperCase() {return toUpperCase(Locale.getDefault());}

 

为什么形参的参数没有对应上呢

下面来解释 

抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法局限性:不能引用所有类中的成员方法。是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。

package yingyong;import java.util.ArrayList;
import java.util.Collections;/*方法引用的规则:1.需要有函数式接口2.被引用的方法必须已经存在3.被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。4.被引用方法的功能需要满足当前的需求抽象方法形参的详解:第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法局限性:不能引用所有类中的成员方法。是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。*/
public class demo6 {public static void main(String[] args) {/* 方法引用(类名引用成员方法)格式类名::成员方法需求:集合里面一些字符串,要求变成大写后进行输出*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "abc", "bba", "ccd");//拿着流里面的每一个数据,去调用String类中的toUpperCase方法,方法的返回值就是转换之后的结果。list.stream().map(String::toUpperCase).forEach(s->System.out.println(s));}
}

7.引用数组的构造方法


 

package yingyong;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/*
方法引用(数组的构造方法)
格式数据类型[]::new
目的:创建一个指定类型的数组
需求:集合中存储一些整数,收集到数组当中细节:数组的类型,需要跟流中数据的类型保持一致。*/
public class demo7 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);/*格式数据类型[]::new*//* 需求:集合中存储一些整数,收集到数组当中*/Integer[] arr = list.stream().toArray(Integer[]::new);System.out.println(Arrays.toString(arr));/* //收集到数组里Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {@Overridepublic Integer[] apply(int value) {return new Integer[value];}});System.out.println(Arrays.toString(arr));*///}}

练习

ublic class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public Student(String str) {String[] arr = str.split(",");this.name = arr[0];this.age = Integer.parseInt(arr[1]);//张无忌,15}
}
package lx;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/*需求:集合中存储一些字符串的数据,比如:张三,23。收集到Student类型的数组当中*/
public class demo1 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"张三,23","李四,24");//由于集合是String类型的所以要强制转换Student[] arr = list.stream().map(Student::new).toArray(Student[]::new);System.out.println(Arrays.toString(arr));}
}

练习2方法一

package lx;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.IntFunction;/**   技巧:*       1.现在有没有一个方法符合我当前的需求*       2.如果有这样的方法,这个方法是否满足引用的规则*       静态   类名::方法名*       成员方法*       构造方法  类名::new* */
public class demo2 {public static void main(String[] args) {/* 需求:*      创建集合添加学生对象学生对象属性:name,age要求:*      获取姓名并放到数组当中使用方法引用完成*/Student s1 = new Student("张三", 18);Student s2 = new Student("李四", 19);Student s3 = new Student("王五", 28);ArrayList<Student> list = new ArrayList<>();Collections.addAll(list, s1, s2, s3);//先获取每一个流 ,把每一个流转换成String 类型的nameString[] arr = list.stream().map(new Function<Student, String>() {@Overridepublic String apply(Student student) {return student.getName();}}).toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(arr));}
}

方法2

package lx;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;/**   技巧:*       1.现在有没有一个方法符合我当前的需求*       2.如果有这样的方法,这个方法是否满足引用的规则*       静态   类名::方法名*       成员方法*       构造方法  类名::new* */
public class demo3 {public static void main(String[] args) {/* 需求:*      创建集合添加学生对象学生对象属性:name,age要求:*      获取姓名并放到数组当中使用方法引用完成*/Student s1 = new Student("张三", 18);Student s2 = new Student("李四", 19);Student s3 = new Student("王五", 28);ArrayList<Student> list = new ArrayList<>();Collections.addAll(list, s1, s2, s3);String[] arr = list.stream().map(Student::getName).toArray(String[]::new);System.out.println(Arrays.toString(arr));}
}
抽象方法形参的详解:
第一个参数:表示被引用方法的调用者,决定了可以引用哪些类中的方法在Stream流当中,第一个参数一般都表示流里面的每一个数据。假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用String这个类中的方法第二个参数到最后一个参数:跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法

对象名引用方法名只能---被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。

类名引用方法名,由于引用的方法没有第二个参树,说明被引用的方法是需要无参的成员方法刚好满足

题目3

package lx;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;/**   需求:*       创建集合添加学生对象*       学生对象属性:name,age*   要求:*       把姓名和年龄拼接成:张三-23的字符串,并放到数组当中*       使用方法引用完成* */
public class demo4 {public static void main(String[] args) {Student s1 = new Student("张三", 18);Student s2 = new Student("李四", 19);Student s3 = new Student("王五", 28);ArrayList<Student> list = new ArrayList<>();Collections.addAll(list, s1, s2, s3);String[] arr = list.stream().map(Student::pj).toArray(String[]::new);System.out.println(Arrays.toString(arr));}
}
 public String pj(){return name+"-"+age;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/379868.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP房产中介租房卖房平台微信小程序系统源码

​&#x1f3e0;【租房卖房新选择】揭秘房产中介小程序&#xff0c;一键搞定置业大事&#xff01;&#x1f3e1; &#x1f50d;【开篇&#xff1a;告别繁琐&#xff0c;拥抱便捷】&#x1f50d; 还在为找房子跑断腿&#xff1f;为卖房发愁吗&#xff1f;今天给大家安利一个超…

JavaScript 获取 url(get)参数

https://andi.cn/page/621584.html

pytorch学习(八)Dataset加载分类数据集

我们之前用torchvision加载了pytorch的网络数据集&#xff0c;现在我们用Dataset加载自己的数据集&#xff0c;并且使用DataLoader做成训练数据集。 图像是从网上下载的&#xff0c;网址是 点这里&#xff0c;标签是图像文件夹名字。下载完成后作为自己的数据集。 1.加载自己…

PyTorch 深度学习实践-循环神经网络基础篇

视频指路 参考博客笔记 参考笔记二 文章目录 上课笔记基于RNNCell实现总代码 基于RNN实现总代码 含嵌入层的RNN网络嵌入层的作用含嵌入层的RNN网络架构总代码 其他RNN扩展基本注意力机制自注意力机制&#xff08;Self-Attention&#xff09;自注意力计算多头注意力机制&#xf…

RPC与服务的注册发现

文章目录 1. 什么是远程过程调用(RPC)?2. RPC的流程3. RPC实践4. RPC与REST的区别4.1 RPC与REST的相似之处4.2 RPC与REST的架构原则4.3 RPC与REST的主要区别 5. RPC与服务发现5.1 以zookeeper为服务注册中心5.2 以etcd为服务注册中心 6. 小结参考 1. 什么是远程过程调用(RPC)?…

TCP三次握手与四次挥手详解

1.什么是TCP TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的通信协议&#xff0c;属于互联网协议族&#xff08;TCP/IP&#xff09;的一部分。TCP 提供可靠的、顺序的、无差错的数据传输服务&…

win11家庭版怎么升级专业版

随着Windows 11的推出&#xff0c;许多用户享受到了全新的用户界面和功能。然而&#xff0c;Windows 11家庭版在某些高级功能上有所限制&#xff0c;例如&#xff0c;组策略管理、远程桌面连接等。为了满足更多的工作需求&#xff0c;许多用户希望将Windows 11家庭版升级到专业…

十、Java集合 ★ ✔(模块18-20)【泛型、通配符、List、Set、TreeSet、自然排序和比较器排序、Collections、可变参数、Map】

day05 泛型,数据结构,List,Set 今日目标 泛型使用 数据结构 List Set 1 泛型 1.1 泛型的介绍 ★ 泛型是一种类型参数&#xff0c;专门用来保存类型用的 最早接触泛型是在ArrayList&#xff0c;这个E就是所谓的泛型了。使用ArrayList时&#xff0c;只要给E指定某一个类型…

分布式IO系统BL201 Profinet耦合器

BL201耦合器是一个数据采集和控制系统&#xff0c;基于强大的32 位微处理器设计&#xff0c;采用Linux操作系统&#xff0c;是一种模块化的分布式I/O系统。该系统由3部分组成&#xff1a;现场总线耦合器和各种类型的&#xff08;数字和模拟信号以及特殊功能&#xff09;I/O模块…

Keka for Mac v1.4.3 中文下载 解压/压缩工具

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试1、打开软件2、文件访问权限修改3、访达扩展 安装完成&#xff01;&#xff…

Ubantu 使用 docker 配置 + 远程部署 + 远程开发

大家好我是苏麟 , Ubantu 一些配置 . 视频 : 服务器很贵&#xff1f;搞台虚拟机玩玩&#xff01;保姆级 Linux 远程开发教程_哔哩哔哩_bilibili Docker安装及配置 安装命令 : sudo apt install docker.io 查看版本号 : docker -v 查看虚拟机地址命令 : ifconfig 虚拟机地址 或…

【Android】 dp与sp,加冕为王

目录 重要概念 屏幕尺寸 屏幕分辨率 屏幕像素密度 基础知识&#xff1a; ppi pt DPI 的定义和重要性 Android 中的 DPI 级别 px dp&#xff08;Density Independent Pixels&#xff09; sp&#xff08;Scale-independent Pixels&#xff09; 安卓的dp/dip、sp 虚拟…

PlantUML-UML 绘图工具安装、Graphviz安装、本地使用/在线使用、语法、图示案例

文章目录 前言本地安装vscode安装插件下载安装Graphviz配置Graphviz环境变量测试 在线使用演示PlantUML语法总结活动图&#xff08;新语法&#xff09;时序图类图用例图其他图 更多相关内容可查看 前言 本篇提供两种使用方式分别为 在线使用地址1&#xff1a;https://www.pla…

【日常记录】【插件】excel.js导出的时候给单元格设置下拉选择、数据校验等

文章目录 1. 代码基本结构2. 导出的excel 某单元格的值设置为下拉选择3. 如何把下拉选择项设置为动态4. 单元格设置校验、提示5. 在WPS上的设置 1. 代码基本结构 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><…

Gitee使用教程2-克隆仓库(下载项目)并推送更新项目

一、下载 Gitee 仓库 1、点击克隆-复制代码 2、打开Git Bash 并输入复制的代码 下载好后&#xff0c;找不到文件在哪的可以输入 pwd 找到仓库路径 二、推送更新 Gitee 项目 1、打开 Git Bash 用 cd 命令进入你的仓库&#xff08;我的仓库名为book&#xff09; 2、添加文件到 …

容器化部署prometheus后再监控docker容器

一、主机部署Prometheus、cadvisor、grafana、node-exporter 1、部署cadvisor收集节点容器信息 docker run -v /:/rootfs:ro -v /var/run:/var/run/:rw -v /sys:/sys:ro -v /var/lib/docker:/var/lib/docker:ro -p 8080:8080 --detachtrue --namecadvisor google/cadvisor 2、…

在线 PDF 制作者泄露用户上传的文档

两家在线 PDF 制作者泄露了数万份用户文档&#xff0c;包括护照、驾驶执照、证书以及用户上传的其他个人信息。 我们都经历过这样的情况&#xff1a;非常匆忙&#xff0c;努力快速制作 PDF 并提交表单。许多人向在线 PDF 制作者寻求帮助&#xff0c;许多人的祈祷得到了回应。 …

PolarisMesh源码系列--Polaris-Go注册发现流程

导语 北极星是腾讯开源的一款服务治理平台&#xff0c;用来解决分布式和微服务架构中的服务管理、流量管理、配置管理、故障容错和可观测性问题。在分布式和微服务架构的治理领域&#xff0c;目前国内比较流行的还包括 Spring Cloud&#xff0c;Apache Dubbo 等。在 Kubernete…

golang开发环境搭建与踩坑记录

文章目录 一、安装下载1、go环境2、ide 二、基本使用1、运行2、结构体与方法函数指针3、闭包4、指针5、map6、接口7、异常 三、包管理1、go mod语法2、项目下载所有依赖 一、安装下载 1、go环境 下载地址&#xff1a;https://go.dev/dl/ 或者&#xff1a;https://golang.goog…

算法基础之回溯法

本文将详细介绍回溯法的基本原理和适用条件&#xff0c;并通过经典例题辅助读者理解回溯法的思想、掌握回溯法的使用。本文给出的例题包括&#xff1a;N皇后问题、子集和问题。 算法原理 在问题的解空间树中&#xff0c;回溯法按照深度优先的搜索策略&#xff0c;从根结点出发…