首页 > 技术文章 > 【Java8 新特性 7】自定义函数式接口

innn 2021-08-05 22:12 原文

一、函数式接口简介

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

如定义了一个函数式接口如下:

package com.panasonic.mes.guor.service;

@FunctionalInterface
public interface CalFunctionalInterface<T, R> {
    R cal(T t1, T t2);
}

二、Java8自带的一些函数式接口

1、功能性接口Function  

2、断言性接口:Predicate

3、供给性接口:Supplier

4、消费性接口:Consumer 

这四大接口的介绍,这里我就不多做解释了,不想重复发文。

大家可以去我的【Java8 新特性 2】函数式接口 + Lamda表达式推导过程学习。

三、自定义函数式接口

1、简单的计算类型

@FunctionalInterface
public interface CalFunctionalInterface<T, R> {
    R cal(T t1, T t2);
}
/**
 * 通过自定义函数式接口实现数值运算
 *
 * @return 3
 */
private static void calTest01() {
    CalFunctionalInterface<Integer, Integer> add = (t1, t2) -> t1 + t2;
    Integer cal = add.cal(1, 2);
    System.out.println(cal.toString());
}

/**
 * 将函数式接口当参数传入 test02(2, 3, (t1, t2) -> t1 * t2);
 *
 * @param t1
 * @param t2
 * @param calFI
 * @return 6
 */
private static void calTest02(Integer t1, Integer t2, CalFunctionalInterface<Integer, Integer> calFI) {
    Integer cal = calFI.cal(t1, t2);
    System.out.println(cal.toString());
}

2、类型转换

package com.example.demo.java8;

@FunctionalInterface
public interface ConvertFunctionInterface<T, R> {
    R convert(T t);
}
/**
 * 通过自定义函数式接口实现数据类型转换
 *
 * @return 24
 */
private static void convertTest01() {
    ConvertFunctionInterface<Integer, String> convert = t -> String.valueOf(t);
    String ret = convert.convert(2);
    System.out.println(ret+4);
}

/**
 * 使用"::"运算符更精简
 *
 * @return 24
 */
private static void convertTest02() {
    ConvertFunctionInterface<Integer, String> convert = String::valueOf;
    String ret = convert.convert(2);
    System.out.println(ret+4);//24
}

/**
 * 使用"::"运算符更精简
 * convertTest03(2, String::valueOf);
 *
 * @return 24
 */
private static void convertTest03(Integer t, ConvertFunctionInterface<Integer, String> convertFI) {
    String ret = convertFI.convert(t) + 4;
    System.out.println(ret);
}

/**
 * convertTest04("myFunctionInterfaceTest", ObjectUtil::hump2Line);
 *
 * @param t
 * @param convertFI
 * @return my_function_interface_test
 */
private static void convertTest04(String t, ConvertFunctionInterface<String, String> convertFI) {
    String ret = convertFI.convert(t);
    System.out.println(ret);
}

java8提供了Function接口(接收一个功能参数t,并返回一个功能结果R。)

所以,一定要了解清楚,你要定义的方法,是否已经存在,不要重复造轮子,编写代码的大忌,费力不讨好。 

/**
 * java8提供了Function接口(接收一个功能参数t,并返回一个功能结果R。)
 *
 * convertTest05("myFunctionInterfaceTest", ObjectUtil::hump2Line);
 *
 * @param t
 * @param convertFI
 * @return my_function_interface_test
 */
private static void functionTest05(String t, Function<String, String> function) {
    String ret = function.apply(t);
    System.out.println(ret);//my_function_interface_test
}

3、方法型接口

@FunctionalInterface
public interface LogFunction {
    public void log();
}
public static  void logTest01(LogFunction logFunction){
    logFunction.log();
}

public static  void logTest011(){
    //调用log方法,方法的参数是一个接口,所以可以传递接口的实现类对象
    logTest01(new LogFunction() {
        @Override
        public void log() {
            System.out.println("函数式接口练习");
        }
    });
}

//调用log方法,方法的参数是一个函数式接口,所以,可以使用lambda表达式
public static  void logTest012(){
    //调用log方法,方法的参数是一个接口,所以可以传递接口的实现类对象
    logTest01(() -> {
        System.out.println("函数式接口练习");
    });
}

//简化lambda表达式
public static  void logTest013(){
    logTest01(() -> System.out.println("函数式接口练习"));
}

4、带泛型的方法型函数

package com.example.demo.java8;

@FunctionalInterface
public interface LogFunction2<T extends Student> {
    public void log(T t);
}
public static  void logTest02(Student student, LogFunction2 logFunction2){
    logFunction2.log(student);
}

public static  void logTest021(Student student){
    logTest02(student, new LogFunction2<Student>() {
        @Override
        public void log(Student t) {
            String ret = t.getId() + "->" + t.getName() + "->" + t.getAge();
            System.out.println(ret);//1->z->18
        }
    });
}

// lambda表达式写法
public static  void logTest022(Student student){
    logTest02(student, (Student t) -> {
        String ret = t.getId() + "->" + t.getName() + "->" + t.getAge();
        System.out.println(ret);
    });
}

5、带多个泛型的功能型函数

package com.example.demo.java8;

@FunctionalInterface
public interface LogFunction3<T extends Student, R extends Teacher> {
    public R build(T t);
}
public static  void logTest03(Student student, LogFunction3 logFunction3){
    logFunction3.build(student);
}

// Teacher(id=1, name=z)
public static  void logTest031(Student student){
    logTest03(student, new LogFunction3<Student, Teacher>() {
        @Override
        public Teacher build(Student s) {
            Teacher t = new Teacher();
            t.setId(s.getTeacherId());
            t.setName(s.getTeacherName());
            System.out.println(t);
            return t;
        }
    });
}

6、实体类

package com.example.demo.java8;

import lombok.Data;

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Integer teacherId;
    private String teacherName;
}

往期精彩内容:

Java知识体系总结

【全栈最全Java框架总结】SSH、SSM、Springboot

超详细的springBoot学习笔记

常见数据结构与算法整理总结

Java设计模式:23种设计模式全面解析

Java面试题总结(附答案)

10万字208道Java经典面试题总结(附答案,建议收藏)

MySql知识体系总结

Linux知识体系总结

Redis知识体系总结

推荐阅读