函数式编程

1、函数式编程

相比于面向对象语言,函数式编程强调怎么做,而不是对象。Lambda表达式就是函数式编程思想的体现。

2、Lambda表达式简单例子

Lambda表达式是JDK 8开始后的一种新语法形式,用来简化匿名内部类的代码写法。

简单例子:

// 原来的写法
list.sort(new Compartor<Integer>( {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
// lambda写法
list.sort((Integer o1, Integer o2) -> {
	return o1 - o2;
});
// lambda的简化写法,不需要声明参数类型,只有一个语句则无需大括号,只有一个函数返回表达式则无需写return
list.sort((o1, o2) -> o1 - o2;);

可见Lambda表达式只包含参数、箭头操作符、函数体(可能包括返回值)

3、lambda表达式写法

  • 不需要声明参数类型,编译器可以统一识别参数值
  • 一个参数无需使用圆括号,但无参数或多个参数需要使用圆括号
  • lambda体包含一个语句时,无需使用大括号
  • 如果主体只有一个函数返回表达式,编译器会自动返回值,无需大括号

1.无参,无返回值

  @Test
  public void test01(){
    Runnable runnable=()-> System.out.println("Runnable 运行");
    runnable.run();//结果:Runnable 运行
  }

lambda表达式只用于创建只有一个抽象方法的接口,此处是匿名内部类的替代写法;接口可以进行实例化,只需要在new后将接口中未实现的方法进行实现就好,这种做法其实是匿名内部类的做法,本质上讲还是类的实例化

2.一个参数,无返回值

  @Test
  public void test02(){
    Consumer<String> consumer=(x)-> System.out.println(x);
    consumer.accept("Hello Consumer");//结果:Hello Consumer
  }

括号省略:

  public void test02(){
    Consumer<String> consumer=x-> System.out.println(x);
    consumer.accept("Hello Consumer");//结果:Hello Consumer
  }

3.两个参数,Lambda体中多条语句

  @Test
  public void test04(){
    Comparator<Integer> com=(x, y)->{
      System.out.println("函数式接口");
      return Integer.compare(x,y);
    };
    System.out.println(com.compare(2,4));//结果:-1
  }

4.两个以上参数,有返回值,若Lambda体中只有一条语句,return和大括号都可以省略不写(不可以只省略大括号)

  @Test
  public void test05(){
    Comparator<Integer> com=(x, y)-> Integer.compare(x,y);
    System.out.println(com.compare(4,2));//结果:1
  }

4、注意事项

(1)接口中只有一个抽象方法时,才能使用lambda表达式

(2)必须有上下文环境,才能推导出lambda表达式对应的接口
什么意思呢?
例如,普通的对于lambda表达式的使用是这样的:

new Thread(() -> System.out.println("线程开启")).start();

也可以使用接口声明来作为上下文:

Runnable r = () -> System.out.println("线程开启");

5、匿名内部类与Lambda表达式的区别

(1)lambda表达式只能用于仅有一个抽象方法的接口,匿名内部类可以用于含有多个抽象方法的接口,实现所有方法即可。
(2)匿名内部类还可以用于抽象类和实现类对应接口的方法匿名实现,lambda表达式只能用于接口。
(3)匿名内部类会产生额外的class文件

6、接口

1)包含的内容:

  • public static final 静态常量
  • public abstract 抽象方法
  • 默认方法(jdk8)
  • 静态方法(jdk8)
  • 私有方法(jdk9)

2)为什么增加默认方法?

一个接口中本来有两个方法,现在需要增加新的抽象方法,但只需要部分类去实现即可,在jdk8之前的做法是:重新定义一个接口来继承原来的接口,并且其中包含了新增方法。那么需要实现新增方法的类直接实现此子接口即可。原来的实现类无需实现新功能。

但这样做的坏处就是,随着系统开发的功能越来越丰富,接口数量越来越多,需要维护的东西也变得复杂和庞大。

所以增加了默认方法,并且可以在其中实现业务功能,那么别的已实现类也不用额外去实现这个方法了,直接拿来用就可以。当然了,默认方法也可以再次被重写,重写时不用加default关键字

3)静态方法

实现方式和普通类中的一样,在接口中实现静态方法。但使用的时候,只能通过接口名去调用,不可以使用对象名或实现类的名字调用。为什么这样规定?因为java中的类可以实现多个接口,如果这多个接口中包含了名字一样的静态方法,那么通过对象调用此方法时,编译器就不知道到底调用的是哪个接口中的方法。

4)私有方法

当默认方法和静态方法之间有相同的代码时,考虑将它们提取成一个方法,并且隐藏起来,只在默认方法和静态方法中保留对于这段私有代码的调用入口。私有方法可以是普通私有方法,也可以是静态私有方法。但注意,静态方法不能调用非静态方法,所以想要用私有方法代替静态方法内部的重复代码,就将私有方法声明为静态的。

定义格式和在类中一样

7、 函数式接口

即只包含一个抽象方法的接口,我们可以通过Lambda表达式来创建该接口的实现对象。例如Runnable接口

java内置的4大函数式接口:
在这里插入图片描述
其他的函数式接口:
在这里插入图片描述

8、 方法引用

(1)体验一下

我们知道,lambda表达式为函数式接口提供了方法的实现,如果已经有这个方法的实现,我们就不用再使用lambda表达式实现一遍了,直接将实现好的方法引用过来即可。

// 接口
public interface Printable {
    void printString(String s);
}
// 使用Printable的方法printString
public static void main(String[] args) {
//        usePrintable((s)-> System.out.println(s)); // 传统的lambda表达式
        
        usePrintable(System.out::println); // System.out对象已经实现有println方法,我们直接引用它,不用管参数,只引用进来它的名字,参数会被自动传给println方法

}
static void usePrintable(Printable p) {
    p.printString("test......");
}

(2)正式介绍

::叫做方法引用符,通过方法的名字来指向一个方法,主要是为了复用已经实现的方法。方法引用是Lambda表达式的另外一种表现形式。无需指定参数类型,也无需指定重载形式,他们都会被自动推导

主要分为四种:

1)引用静态方法

类名::静态方法名

例如:Integer::parseInt

调用接口中抽象方法时,形参全部传递给静态方法

2)引用对象的实例方法

对象名::实例方法名

对象是需要提前创建好的

调用接口中抽象方法时,形参全部传递给实例方法

3)引用类的实例方法

类名::实例方法名

调用接口中抽象方法时,第一个参数是调用该方法的那个对象,后面的参数是引用的方法的参数

4)引用构造器

类名::new

调用接口中抽象方法时,形参全部传递给构造器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值