面向对象通识20(函数式接口)

概述函数式接口

引例:函数式接口:只有一个抽象方法的接口

  1. @FunctionalInterface
  2. //用于修饰函数式接口,作用域之前讲的@Override类似,都是用于报错
  3. //当接口内有两个
  4. public interface Walkable {
  5. public void move();
  6. static int sum(int a,int b){
  7. return a+b;
  8. }//实例方法1
  9. default void foo(){
  10. }//实例方法2
  11. }

Lambda表达式

语法格式

  1. public class LambdaTest {
  2. public static void main(String[] args) {
  3. Walkable mv=new Walkable() {
  4. @Override
  5. public void move() {
  6. //类体通常是实现抽象方法
  7. System.out.println("Just walk");
  8. }
  9. };
  10. //mv的编译类型是Walkable
  11. //Walkable声明了几个方法,mv就可以调用几个方法
  12. mv.move();
  13. mv.foo();
  14. Walkable md=new Walkable() {
  15. @Override
  16. public void move() {
  17. }
  18. };
  19. //此为Lambda表达式
  20. Walkable mc=()->{
  21. };
  22. /*上述等同于
  23. Walkable mc=new Walkable() {
  24. @Override
  25. public void move() {
  26. }
  27. };
  28. */
  29. }
  30. }

综上可见Lambda表达式本质就是函数式接口的匿名内部类

——只保留匿名内部类所实现的抽象方法,并且只留方法的形参列表和方法体

在此可以理解为一个匿名内部类直接指向一个函数式接口唯一存在的抽象方法

  1. 接口名 对象名=(形参列表)->{
  2. //抽象方法所需重写的方法体部分
  3. }

Lambda表达式的简化写法

  • 通常写形参列表的时候都省略写形参类型
    举例:
    1. @FunctionalInterface
    2. public interface Runable {
    3. void runner(String name,int age);
    4. }
  • 当函数式接口抽象方法的形参列表只有一个参数时,Lambda表达式形参列表的参数类型和括号都可以省略
  • 当函数式接口抽象方法的方法体中仅有一句语句时,Lambda表达式方法体的花括号也可以省去
  • 当函数式接口抽象方法的方法体中仅有一句语句,且这条语句是return语句,可以省略return关键字
  1. public interface Lambda3 {
  2. int value(int a);
  3. }
  1. public class LambdaTest3 {
  2. public static void main(String[] args) {
  3. //省略形参类型,形参名,省略花括号,省略return关键字
  4. Lambda3 n1=n->n*n;
  5. System.out.println(n1.value(3));
  6. }
  7. }
  8. /*
  9. 9
  10. */

Lambda表达式所表示的方法引用和构造器引用

省略引用类方法

  • 引用类方法——只有当方法体只有一条代码的时候才可以使用
  • 本质——进一步省略,完全省略了形参列表和箭头

原有:(参数列表)->某个类.某个方法

省略后:某个类::某个方法

举例:

  1. public interface Fn {
  2. double call(double a,double b);
  3. }
  1. public class 引用类方法 {
  2. public static void main(String[] args) {
  3. Fn fn1=(d1,d2)->Math.hypot(d1,d2);
  4. System.out.println(fn1.call(3.0,4.0));
  5. Fn fn2=Math::hypot;
  6. /* 与上一行本质相同
  7. Fn fn2=(d1,d2)->Math.hypot(d1,d2);
  8. */
  9. System.out.println(fn2.call(3,4));
  10. }
  11. }

省略引用实例方法

原有:(参数1,其他参数)->参数1.某个方法(其他参数)

省略后:参数1的类型::某个方法

举例:

  1. @FunctionalInterface
  2. public interface Converter {
  3. String change(String a, int b, int c);
  4. }
  1. public class 引用实例方法 {
  2. public static void main(String[] args) {
  3. Converter str=(a,b,c)->a.substring(b,c);
  4. Converter str1=String::substring;
  5. System.out.println(str.change("java",1,3));
  6. System.out.println(str1.change("python",2,4));
  7. }
  8. }

省略引用特定对象的实例方法

原有:(参数列表)->某个对象.某个方法(参数列表)

简化:某个对象::某个方法

举例:

  1. @FunctionalInterface
  2. public interface Conter {
  3. String choose(int a,int b);
  4. }
  1. public class 引用特殊的实例方法 {
  2. public static void main(String[] args) {
  3. Conter c1=(b,c)->"another one".substring(b,c);
  4. //同样省略了形参列表和箭头
  5. Conter c2="anther two"::substring;
  6. System.out.println(c1.choose(2,4));
  7. System.out.println(c2.choose(2,4));
  8. }
  9. }

构造器引用

原有:参数列表->new 构造器(参数列表)

简化后:构造器名::new

举例:

  1. import java.util.Date;
  2. @FunctionalInterface
  3. public interface Test {
  4. Date cal(int a, int b, int c);
  5. }
  1. import java.util.Date;
  2. public class TestTest {
  3. public static void main(String[] args) {
  4. Test a1=(a,b,c)->new Date(a,b,c);
  5. System.out.println(a1.cal(109,3,7));
  6. Test a2=Date::new;
  7. System.out.println(a2.cal(122,3,20));
  8. }
  9. }
  10. /*
  11. Tue Apr 07 00:00:00 CST 2009
  12. Wed Apr 20 00:00:00 CST 2022
  13. */