首页 > 编程语言 >Java8函数式接口, 方法引用, 构造器引用, 数组引用

Java8函数式接口, 方法引用, 构造器引用, 数组引用

时间:2023-11-23 13:44:19浏览次数:29  
标签:void System 接口 Java8 引用 println public out

函数式(Functional)接口

  • 只包含一个抽象方法的接口,称为函数式接口。
  • 你可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明
  • 我们可以在一个接口上使用@Functionallnterface注解,这样做可以检查它是否是一个函数式接口。同时javadoc也会包含一条声明,说明这个接口是一个函数式接口。
  • 在java.util.function包下定义了Java8的丰富的函数式接口

如何理解函数式接口

  • Java从诞生日起就是一直倡导“一切皆对象”,在Java里面面向对象(OOP)编程是一切。但是随着python、scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,也即java不但可以支持OOP还可以支持OOF(面向函数编程)
  • 在函数式编程语言当中,函数被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。
  • 但是在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型一函数式接口
  • 简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。
  • 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写

Java内置四大核心函数式接口以及使用

img

// Consumer
public void happyTime(double money, Consumer<Double> con){
    con.accept(money);
}

@Test
public void test1(){
    happyTime(200, money -> {
        System.out.println("happy: " + money);
    });
}
// Predicate
public List<String> filterString(List<String> list, Predicate<String> pred){
    List<String> res = new ArrayList<>();
    for(String s : list) {
        if(pred.test(s)){
            res.add(s);
        }
    }
    return res;
}

@Test
public void test2(){
    List<String> list = Arrays.asList("北京","南京","西京","广东","东京");
    List<String> res = filterString(list, str -> !str.contains("京"));
    System.out.println(res);
}

方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!(针对情况1和2)
格式:使用操作符“::”将类(或对象)与方法名分隔开来。
如下三种主要使用情况:

  1. 对象 :: 实例方法名(非静态方法)
  2. 类 :: 静态方法名
  3. 类 :: 实例方法名(非静态方法)

对象调用静态方法实际上相当于类调用静态方法.

使用情景

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

// 对象 :: 实例方法
@Test
public void test1(){
    // Consumer中的void accept(T t)
    // PrintStream中的void println(T t)
    // 两种都是泛型T, 可以用
    Consumer<String> con1 = str -> System.out.println("str");
    Consumer<String> con2 = System.out::println;
    PrintStream out = System.out;
    Consumer<String> con3 = out::println;
    con3.accept("con3");
}

@Test
public void test2(){
    // Supplier中的T get()
    // Employee中的String getName()
    // 可以做类型推断
    Employee emp = new Employee(1001, "tom", 23, 5600);
    Supplier<String> sup1 = () -> emp.getName();
    Supplier<String> sup2 = emp::getName;
    System.out.println(sup2.get());
}
// 类 :: 静态方法
@Test
public void test3(){
    // Comparator中的int compare(T t1, T t2)
    // Integer中的int compare(T t1, T t2)
    Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
    Comparator<Integer> com2 = Integer::compare;
    System.out.println(com2.compare(3, 4));
}

@Test
public void test4(){
    // Function<T, R>
    // Function中的R apply(T t), 
    // Math中的Long round(Double d)
    // 注意参数类型要对上
    Function<Double, Long> f = new Function<Double, Long>() {
        @Override
        public Long apply(Double aDouble) {
            return null;
        }
    };
    Function<Double, Long> f2 = Math::round;
    Function<Double, Long> f3 = d -> Math.round(d);
    System.out.println(f2.apply(4.0));
}
// 类 :: 实例方法名(非静态方法)
// 注意调用者是谁, 比如t1.comparaTo(t2)
@Test
public void test5(){
    // Comparator中的 int compare(T t1, T t2)
    // String中的 int t1.compareTo(t2)
    Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2);
    Comparator<String> com2 = String :: compareTo;
    System.out.println(com2.compare("a", "e"));
}

@Test
public void test6(){
    //BiPredicate中的boolean test(T t1, T t2);
    //String中的boolean t1.equals(t2)
    BiPredicate<String, String> bp1 = (t1, t2) -> t1.equals(t2);
    BiPredicate<String, String> bp2 = String :: equals;
    System.out.println(bp2.test("a", "a"));
}

@Test
public void test7(){
    // Function中的 R apply(T t)
    // Employee中的String getName()
    Function<Employee, String> f = Employee::getName;
    Employee emp = new Employee(1234,"tmo", 12, 2314.23);
    System.out.println(f.apply(emp));
}

构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表 和 构造器的形参列表一致。抽象方法的返回值类型即为构造器所属的类的类型.

@Test
public void test1(){
    // Supplier的T get()
    // Employee的空参构造器, 返回Employee对象
    Supplier<Employee> sup1 = Employee :: new;
    System.out.println(sup1.get());
}

@Test
public void test2(){
    // Function中的 R apply(T t)
    Function<Integer, Employee> f = Employee :: new;
    System.out.println(f.apply(1234));
}

@Test
public void test3(){
    // BiFunction中的 R apply(T t, U u)
    BiFunction<Integer, String, Employee> bf = (id, name) -> new Employee(id, name);
    BiFunction<Integer, String, Employee> bf1 = Employee::new;
    System.out.println(bf1.apply(1234, "joey"));
}

数组引用

把数组看成一种类的类型, 就跟构造器引用没有太大区别了.

@Test
public void test4(){
    Function<Integer, String[]> f = length -> new String[length];
    Function<Integer, String[]> f1 = String[] :: new;
    System.out.println(f1.apply(5).length);
}

附录

public class Employee {
    private int id;
    private String name;
    private int age;
    private double salary;
    // ... getter, setter, toString, constructor
}

标签:void,System,接口,Java8,引用,println,public,out
From: https://www.cnblogs.com/joey-redfield/p/17851365.html

相关文章

  • 十三、指针和引用(三)
    十三、指针和引用(三)1、std::unique_ptr(唯一智能指针)1)概念std::unique_ptr是所谓的智能指针的一种,主要目的是为了解决原生指针安全性不足的弊端//std::unique_ptr指针的声明语法std::unqiue_ptr<类型>变量名称{};//示例std::unique_ptr<int>ptrA{std::make_unique<int>(1......
  • 001swagger2--接口文档生成利器
    1.配置在springboot整合swagger21.1引入jar包<dependency><groupId>com.allen.pan</groupId><artifactId>allen-pan-core</artifactId><version>1.0</version></dependency&g......
  • delphi 第一次接触与配置接口
    首先说明一下,这是我平生第一次接到接口文档,认知有限,写得不对的地方,请大佬们多多指点.下面是一个智能刀具柜关于库存查询的接口文档: 上面的参数中,appid和sign中的appsecret和macno是设备的常量值,要问设备服务商给.上面的接口要分别设置header头和请求参数.而POST提......
  • 接口优化技巧
    大家好,最近看到京东云的一位大佬分享的接口优化方案,感觉挺不错的,拿来即用。建议收藏一波或者整理到自己的笔记本中,随时查阅!下面是正文。一、背景针对老项目,去年做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。本文将给小伙伴们分享一......
  • 当项目中引用了 nuget 包,却在输出时无法找到对应文件时
    可以检查项目文件中对应包的属性是否有PrivateAssets=‘All’这个属性会在最终输出时,不复制相关文件,在nuget包仅在开发过程中使用时会比较有用。参考链接:https://learn.microsoft.com/zh-cn/nuget/consume-packages/package-references-in-project-files#controlling-depen......
  • 如何定义Sping上传文件的接口
    我直接通过拓云智能AI搜索获得了如下的答案。避免了花费太长时间也找不到直接答案。--现在百度广告太多了...在Spring中,通过定义Controll层,来实现接口,上传文件比较特殊,需要注意的点:可以使用@PostMapping注解来定义上传音频文件的接口使用MultipartFile类来接受前端上传......
  • wxid批量转换微信号接口工具,自动转换二维码,开源API分享!
    这个是今天客户定制的,就是从微信群导出了很多WXID,然后实现通过WXID加好友,我就直接调用了微信的接口,说明一下这是微信公开的接口,不存在HOOK或者是逆向技术存在的,公开接口,任何人都可以调用,我就是把接口通过易语言实现了批量生成的功能效果。界面图:  WXID添加效果,不是微信号,是......
  • Java8新特性lambda学习
    Lambda表达式Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。本质:作为函数式接口的实例,没有接口就没意义了.//简单......
  • springboot移动端授权登录请求接口说明
    使用系统内部演示代码,在附件下载方便统一管理用户方便在线用户监控一处编写、处处可用统一鉴权方式1.新增角色、用户组【若已分配可跳过】角色管理-新增专门用于移动等模块-不分配任何后台菜单【DZDS已有】2.新增、修改用户在业务模块添加、修改用户信息,需要同步到sys_user中......
  • Java单列集合Set:HashSet与LinkedHashSet详解,为什么它比List接口更严格?
    上篇我们介绍了单列集合中常用的list接口,本篇我们来聊聊单列集合中的另外一个重要接口Set集合。1、Set介绍java.util.Set接口和java.util.List接口一样,同样实现了Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口......