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.mzph.cn/bicheng/48608.shtml

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

相关文章

2024最新教程,在docker中安装kali,并配置ssh连接

docker的基本使用&#xff1a;搭建高效攻防靶场vulfocus与Docker仓库管理实战&#xff1a;从听说到入门 拉取kali官方镜像 docker pull kalilinux/kali-rolling 启动一个kali镜像&#xff0c;将容器中的22端口映射到主机100端口&#xff0c;方便ssh直接连接 docker run -it…

Java 集合框架:Java 中的优先级队列 PriorityQueue 的实现

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 018 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

用不同的url头利用Python访问一个网站,把返回的东西保存为txt文件

这个需要调用requests模块&#xff08;相当于c的头文件&#xff09; import requests 还需要一个User-Agent头&#xff08;这个意思就是告诉python用的什么系统和浏览器&#xff09; Google Chrome&#xff08;Windows&#xff09;: Mozilla/5.0 (Windows NT 10.0; Win64; x64…

【Git命令】git rebase之合并提交记录

使用场景 在本地提交了两个commit&#xff0c;但是发现根本没有没必要分为两次&#xff0c;需要想办法把两次提交合并成一个提交&#xff1b;这个时候可以使用如下命令启动交互式变基会话&#xff1a; git rebase -i HEAD~N这里 N 是你想要重新调整的最近的提交数。 如下在本地…

vscode配置django环境并创建django项目(全图文操作)

文章目录 创建项目工作路径下载python插件&#xff1a;创建虚拟环境选择虚拟环境在虚拟环境中安装Django创建Django项目 创建项目工作路径 下载python插件&#xff1a; 创建虚拟环境 >python:create 于是会多出一个.venv的目录 选择虚拟环境 在虚拟环境中安装Django …

MySQL 数据库 day 7.16

ok了家人们今天继续记录一下数据库,看看今天学了什么。 一.事物概述 1.1 环境准备 -- 账户表 create table account( id int primary key auto_increment, name varchar(20), money double );insert into account values (null,张三,1000); insert into account values (n…

解决Linux桌面初始化问题

问题 启动vnc桌面&#xff0c;提示问题 定位 从[t]csh手册 可以看到&#xff0c;其初始化流程 经定位&#xff0c;是.cshrc的这段代码存在&#xff0c;导致桌面初始化异常。 [wanlin.wangicinfra-cn-172-16-0-115 ~]$ cat .cshrc ...部分省略... # Environment for anac…

Unity UGUI 之 Canvas Scaler

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.什么是Canvas Scaler Unity - 手册&#xff1a;Canvas Scaler 重点&#xff1a;虽然叫…

【springboot】中使用--WebMvcConfigurer

WebMvcConfigurer 一、页面跳转控制器step1:创建视图&#xff0c;resources/templates/index.htmlstep2:创建SpringMVC配置类step3:测试功能 二、数据格式化step1:创建 DeviceInfo 数据类step2&#xff1a;自定义 Formatterstep3: 登记自定义的 DeviceFormatterstep4: 新建 Con…

Flutter中GetX的用法(超详细使用指南之路由依赖管理篇)

目录 1.前言 2.GetX 依赖管理概述 1.GetX 依赖管理的基本概念 2.与其他依赖管理工具的比较 3. 基础依赖注入 1.Get.put 2.Get.lazyPut 3.Get.putAsync 4.高级依赖注入 1.使用Get.create 2.依赖生命周期管理 5. 参考资料 1.前言 今天这篇博客主要介绍Getx的三大功能…

java基于ssm+vue 药品网购平台

1用户前台功能模块 1.1前台首页 前台首页详情页面&#xff1a;首页、药品信息、疫情常识、保健品推荐、个人中心、后台管理、购物车等操作。程序效果图如下图1所示&#xff1a; 前台页面等内容&#xff0c;如图1所示。 1.2个人中心 在前台页面查看个人中心用户注册、登录&am…

【proteus经典实战】LCD滚动显示汉字

一、简介 Proteus是一款功能丰富的电子设计和仿真软件&#xff0c;它允许用户设计电路图、进行PCB布局&#xff0c;并在虚拟环境中测试电路功能。这款软件广泛应用于教育和产品原型设计&#xff0c;特别适合于快速原型制作和电路设计教育。Proteus的3D可视化功能使得设计更加直…

多任务高斯过程数学原理和Pytorch实现示例

高斯过程其在回归任务中的应用我们都很熟悉了&#xff0c;但是我们一般介绍的都是针对单个任务的&#xff0c;也就是单个输出。本文我们将讨论扩展到多任务gp&#xff0c;强调它们的好处和实际实现。 本文将介绍如何通过共区域化的内在模型(ICM)和共区域化的线性模型(LMC)&…

【Linux知识点汇总】07 Linux系统防火墙相关命令,关闭和开启防火墙、开放端口号

​完整系列文章目录 【Linux知识点汇总】 心血来潮突然想起之前写过的系列文章【Linux知识点汇总】还未完结&#xff0c;那么今天就继续吧 说明&#xff1a;这个系列的内容&#xff0c;在系列【Linux服务器Java环境搭建】中会经常用到&#xff0c;大家可以自行查找相关命令 一、…

Docker搭建本地私有仓库

目录 1.下载运行registry 镜像 2.添加私有镜像仓库地址 3.为镜像添加标签 4.上传到私有仓库 5.查看私有仓库的所有镜像 6.测试私有仓库下载 1.下载运行registry 镜像 docker pull registry docker run -d -v /data/registry:/var/lib/registry -p 5000:5000 --restartal…

PostgreSQL使用(二)——插入、更新、删除数据

说明&#xff1a;本文介绍PostgreSQL的DML语言&#xff1b; 插入数据 -- 1.全字段插入&#xff0c;字段名可以省略 insert into tb_student values (1, 张三, 1990-01-01, 88.88);-- 2.部分字段插入&#xff0c;字段名必须写全 insert into tb_student (id, name) values (2,…

vue3【详解】跨组件通信 -- 依赖注入 provide inject

用于解决跨组件&#xff08;父组件与所有后代&#xff09;数据通信 提供数据 provide 传出数据的组件 &#xff08;通常为父辈组件&#xff09;提供数据 <script setup> import { provide } from vueprovide(/* 注入名 */ message, /* 值 */ hello!) </script>pro…

pycharm中运行.sh文件

最近在跑一个项目代码&#xff0c;里面要运行.sh文件。于是配置了下如何在pycharm中正常运行.sh文件。 首先安装好git&#xff0c;然后 File—>Settings—>Tools—>Terminal—>Shell path&#xff0c;将cmd.exe改成刚刚下载的git的路径&#xff0c;注意选择的是s…

web服务器——虚拟主机配置实战

搭建静态网站 —— 基于 http 协议的静态网站 实验 1 &#xff1a;搭建一个 web 服务器&#xff0c;访问该服务器时显示 “hello world” 欢迎界面 。 实验 2 &#xff1a;建立两个基于 ip 地址访问的网站&#xff0c;要求如下 该网站 ip 地址的主机位为 100 &#xff0c;设置…

web——搭建静态网站——基于http协议的静态网站

实验 4 &#xff1a;建立两个基于域名访问的网站&#xff0c;要求如下&#xff1a; 新建一个网站&#xff0c;域名为 www.ceshi.com &#xff0c;设置网站首页目录为 /www/name &#xff0c;网页内容为 this is test 。 新建一个网站&#xff0c;域名为 rhce.first.day &…