天天看点

函数式编程【1】——初识函数式编程

1.一段话理解函数式编程

首先说一下

函数

方法

的区别,简单的可以理解为同一个东西,都是一个执行块。前者是

面向过程

的叫法,后者是

面向对象

的叫法。所以说函数式编程某种程度上来说也可以理解为方法编程。而写过js的同学应该知道,在js中的函数是允许把另外一个函数作为自身参数的。后来仔细看了《java8实战》,谈一下自己的理解。函数式编程这个概念就是让我们用一种新的思维方式去写java。

2.举个栗子

我们先定义一个简单的

People

接口。

public interface People {
    void say();
}
           

然后定义一个

ZhangSan

类,当我们需要创建

People

实例的时候,显然需要去实现这个接口里的方法。

public class ZhangSan {
    
    People zhangsan = new People() {
        @Override
        public void say() {
               System.out.println("i am zhangsan");
        }
    };
}
           

同样的,创建一个LiSi类,也需要这么操作。

public class LiSi {
    
    People liSi = new People() {
        @Override
        public void say() {
            System.out.println("i am lisi");      
        }
    };
}
           

发现问题了吗?每次创建接口对象的时候,“=”右边的格式是固定的。再者我们创建接口的目的是什么?是为了使用他的方法。那么可以直接使用他的方法而不创建实例吗?java8是这么做的。把上面代码重复的部分改为:

() ->

所以上面的代码也可以写成

public class LiSi {
    
    static People liSi = () -> {
        System.out.println("i am lisi");
    };
}
           

我们可以尝试调用一下liSi的say方法。

public class LiSi {

    static People liSi = () -> {
        System.out.println("i am lisi");
    };

    public static void main(String[] args) {
        liSi.say();
    }
}
           

输出结果: i am lisi

其中 () 是参数列表,这里没有使用参数。 ->是操作符,固定格式不必纠结,{}是方法体。

看到这里你可能会有一点疑惑,我们在定义liSi这个对象的时候,也没有指定它的say方法啊,为什么调用say方法的时候可以实现呢?这就涉及到函数式接口的定义:

有且仅有一个抽象方法

。所以在创建lisi的时候,方法体里实现的就是People接口里的say方法。

当方法体里只有一个表达式的时候,方法体的大括号也可以省略不写

。就像这样:

我们通常通过

@FunctionalInterface

来标示一个函数式接口,也可以不写,它只是起到一个标示作用。

此时lisi就是一个People对象,

且实现了唯一的抽象方法

。现在有一个

talk

方法,需要Peopeo参数:

public static void talk(People people) {
    people.say();
}
           

我们在调用的时候就可以用

lambda表达式

进行替换【理解这一点非常重要,搞清楚这个很方便接下来学习lamda的常用方法和流式编程】:

public static void main(String[] args) {
    talk(() -> System.out.println("i am lisi"));
}
           

因为

talk

方法需要的参数是People,而我们的

() -> System.out.println("i am lisi")

则正是一个实现了People接口唯一抽象方法的实例。此时运行则会输出:

i am lisi

理解这一点则可以开始接下来的学习,lambda常用方法.

链接: