02-详细介绍Java8新特性方法引用,构造引用,数组引用

方法/构造/数组引用

方法引用

当要传递给Lambda体的操作已经有实现的方法时就可以使用方法引用,方法引用和构造器引用就是为了简化Lambda表达式

  • 方法引用可以看做是Lambda表达式深层次的表达,方法引用本质还是Lambda表达式所以也是函数式接口的一个实例
  • 通过方法的名字来指向一个方法可以认为是Lambda表达式的一个语法糖

语法糖(Syntactic sugar)也译为糖衣语法是指计算机语言中添加的某种对语言的功能没有影响但是更方便程序员使用的语法

  • 使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会

方法引用格式: 使用方法引用操作符 "::" 将类或对象方法名分隔开来,要求Lambda体只有一句语句并且是调用一个对象/类的方法

  • 因为引用的方法的形参和返回值函数式接口抽象方法的形参和返回值都相同,所以引用方法的形参可以省略
  • 情况1:对象::实例方法名
  • 情况2:类::静态方法名
  • 情况3:类::实例方法名

先写一个Employee实体类

java 复制代码
public class Employee {
    private String name;
    private Integer id;
    // get和set方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    // 构造方法
    public Employee() {
    }
    public Employee(Integer id) {
        this.id = id;
        this.name = name;
    }
    public Employee(Integer id,String name) {
        this.id = id;
        this.name = name;
    }
}

**对象::非静态方法:接口抽象方法a在被重写时使用了某一个对象的方法b,如果方法a和b的形参列表,返回值类型都相同,则可以使用方法b实现对方法a的重写替换 **

  • Consumer中的void accept(T t)和PrintStream中的void println(T t)形参列表均为(T t)以及返回值均为void
  • Supplier中的T get()和Employee中的String getName()形参列表均为空以及返回值均为String
java 复制代码
@Test
public void test() {
    // 使用Lambda表达式
    Consumer<String> consumer01 = s -> System.out.println(s);
    consumer01.accept("她的手只有我的手四分之三那麼大");
    System.out.println("-----------------------------");
    // 使用方法引用
    //PrintStream printStream = System.out;
    //Consumer<String> consumer02 = printStream::println;
    Consumer<String> consumer02 = System.out::println;
    consumer02.accept("可我還是沒能抓住");
}
@Test
public void test() {
    Employee emp = new Employee(1001,"Tom");
    // 使用Lambda表达式
    Supplier<String> sup1 = () -> emp.getName();
    System.out.println(sup1.get());
    System.out.println("*******************");
    // 使用方法引用
    Supplier<String> sup2 = emp::getName;
    System.out.println(sup2.get());

}

类::静态方法: :接口抽象方法a在被重写时使用了某一个类的静态方法b,如果方法a和b的形参列表,返回值类型都相同,则可以使用方法b实现对方法a的重写替换

  • Comparator中的int compare(T t1,T t2)和Integer中的int compare(T t1,T t2)形参列表均为(T t1,T t2)以及返回值均为int
  • Function中的R apply(T t)和Math中的Long round(Double d)返回值和参数列表为泛型
java 复制代码
@Test
public void test07() {
    // 使用Lambda表达式
    Comparator<Integer> comparator01 = (o1, o2) -> Integer.compare(o1, o2);
    System.out.println(comparator01.compare(20, 77));
    System.out.println("----------------------------");
    // 使用方法引用
    Comparator<Integer> comparator02 = Integer::compare;
    System.out.println(comparator02.compare(94, 21));
}

@Test
public void test08(){
    // 使用Lambda表达式
    Function<Double,Long> function01 = aDouble -> Math.round(aDouble);
    System.out.println(function01.apply(3.141));
    System.out.println("------------------------------");
    // 使用方法引用
    Function<Double,Long> function02 = Math::round;
    System.out.println(function02.apply(2.717));
}

类::实例方法: 抽象方法a在被重写时使用了某一个对象的方法b,如果方法a和b的返回值类型相同但方法b的形参少一个,则可以使用方法b实现对方法a的重写替换

  • 方法a的形参列表中有n个参数方法b有n-1个参数,方法a的第1个参数作为方法b的调用者,方法a的后n-1个参数与方法b的n-1个参数匹配(类型相同或满足多态)
  • Comparator中的int comapre(T t1,T t2)方法和String中的int t1.compareTo(t2)方法
  • BiPredicate中的boolean test(T t1, T t2)方法和String中的boolean t1.equals(t2)方法
  • Function中的R apply(T t)方法和Employee中的String toString()方法
java 复制代码
@Test
public void test5() {
    // 使用Lambda表达式
    Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
    System.out.println(com1.compare("abc","abd"));
    System.out.println("*******************");
    // 使用方法引用
    Comparator<String> com2 = String :: compareTo;
    System.out.println(com2.compare("abd","abm"));
}

@Test
public void test10(){
    // 使用Lambda表达式
    BiPredicate<String,String> biPredicate01 = (o1, o2) -> o1.equals(o2);
    System.out.println(biPredicate01.test("Kyle", "Kyle"));// true
    System.out.println("----------------------------------");
    // 使用方法引用
    BiPredicate<String,String> biPredicate02 = String::equals;
    System.out.println(biPredicate02.test("Violet", "Violet"));// true
}

@Test
public void test7() {
    Employee employee = new Employee(1001, "Jerry");
    // 使用Lambda表达式
    Function<Employee,String> func1 = e -> e.getName();
    System.out.println(func1.apply(employee));
    System.out.println("*******************");
    // 使用方法引用
    Function<Employee,String> func2 = Employee::getName;
    System.out.println(func2.apply(employee));
}


@Test
public void test11(){
    Ememployee employee = new Employee(1001, "Jerry");
    Function<Stu,String> function01 = employee -> employee.toString();
    System.out.println(function01.apply(employee));
    System.out.println("------------------------------");
    Function<Employee,String> function02 = Employee::toString;
    System.out.println(function02.apply(employee employee));
} 

构造器引用

类名::new: 要求Lambda体只有一句语句并且是用来创建一个对象,构造方法的形参列表和返回值(构造器对应类的对象)要与接口中抽象方法一致才可以替换

  • Supplier中的T get()和Employee的无参构造方法Employee()

  • Function中的R apply(T t)和Employee的有参构造方法Employee(id)

  • BiFunction中的R apply(T t,U u)和Employee的有参构造方法Employee(id,name)

java 复制代码
@Test
public void test1(){
    // 传统写法
    Supplier<Employee> sup = new Supplier<Employee>() {
        @Override
        public Employee get() {
            return new Employee();
        }
    };
    System.out.println("*******************");
    // Lambda表达式
    Supplier<Employee>  sup1 = () -> new Employee();
    System.out.println(sup1.get());
    System.out.println("*******************");
    // 构造器引用
    Supplier<Employee>  sup2 = Employee :: new;
    System.out.println(sup2.get());
}

@Test
public void test2(){
    // Lambda表达式
    Function<Integer,Employee> func1 = id -> new Employee(id);
    Employee employee = func1.apply(1001);
    System.out.println(employee);
    System.out.println("*******************");
    // 构造器引用
    Function<Integer,Employee> func2 = Employee :: new;
    Employee employee1 = func2.apply(1002);
    System.out.println(employee1);

}

@Test
public void test3(){
    // Lambda表达式
    BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
    System.out.println(func1.apply(1001,"Tom"));
    System.out.println("*******************");
    // 构造器引用
    BiFunction<Integer,String,Employee> func2 = Employee :: new;
    System.out.println(func2.apply(1002,"Tom"));

}

数组构造引用

数组类型名[]::new: 要求Lambda体只有一条语句并且是创建一个数组对象,接口中抽象方法的形参接收的是数组对象的长度

  • Function中的R apply(T t)和String[]
java 复制代码
@Test
public void test4(){
    // Lambda表达式
    Function<Integer,String[]> func1 = length -> new String[length];
    String[] arr1 = func1.apply(5);
    System.out.println(Arrays.toString(arr1));
    System.out.println("*******************");
    // 数组引用
    Function<Integer,String[]> func2 = String[] :: new;
    String[] arr2 = func2.apply(10);
    System.out.println(Arrays.toString(arr2));

}
相关推荐
晓纪同学32 分钟前
QT-简单视觉框架代码
开发语言·qt
威桑33 分钟前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服36 分钟前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生42 分钟前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans1 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
算法小白(真小白)1 小时前
低代码软件搭建自学第二天——构建拖拽功能
python·低代码·pyqt
唐小旭1 小时前
服务器建立-错误:pyenv环境建立后python版本不对
运维·服务器·python
007php0071 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程