简介
- 面向对象是对数据进行处理,传递值
Peope people = new People(int i,String name);//最典型的构造器都是传值
public int sum(int a,int b){//传的是值,
return a+b;
}
复制代码
-
函数式是一种行为,可以传递行为
-
Lambda的形状
(parm1,parm2,...) -> {
方法体
}
复制代码
为何需要Lambda表达式:
- 在Java 8 之前,我们无法将函数作为参数传递给个方法,也无法声明返回一个函数的方法
- 为了实现将函数作为参数,而加入了Lambda表达式
- 在JavaScript中,函数参数是一个函数,返回值是另一个函数的情况是非常常见的;
- JavaScript是一门非常典型的函数式语言
- 经典的callback
$("button").click(function(){//click方法中传入的callback()方法
$("p").hide(1000);
});
复制代码
@FunctionalInterface
详解
先从遍历这件事说起
public class TraverseTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
for (int i = 0; i < list.size();i++){//远古时期
System.out.println(list.get(i));
}
System.out.println("--------------------");
for (Integer i : list){//近代--迭代器
System.out.println(i);
}
System.out.println("---------------------");
/*
大多数(FunctionalInterface)功能接口仅意味着-功能接口,这严格意味着它们接受输入,
进行一些计算并返回输出。(函数的本质)他们不应该修改任何状态。
Consumer是例外,因为它不返回任何值。它的目的仅仅是修改某些状态。
*/
list.forEach(new Consumer<Integer>() {//现代---forEach
@Override
public void accept(Integer integer) {
int i = integer*integer;//副作用
System.out.println(i);
}
});
list.forEach(integer -> { System.out.println(integer);});
list.forEach(System.out::println);//方法引用,引用System.out对象中的println方法实现accept方法
}
}
复制代码
要素察觉
何谓forEach
?
- 点开源码瞧一瞧
- 信息收集
forEach()
是Iterable
接口中的方法,已经有默认实现- 功能:对迭代器中的每个元素进行操作
- 参数:Consumer ,每个元素要执行的动作
何谓Consumer
?
- 点看源码瞧一瞧
- 信息收集
Consumer
是一个接口,而且是一个functional interface- 里面有一个accept()方法
- 还说与其他functional interface不一样,通过副作用进行操作
- 之所以说不一样,是因为函数一般都有返回值,而Consumer没有返回值。如果它不通过副作用对数据进行改变和操作,那Consumer将没有任何意义,那要Consumer做什么。副作用其实就是指对数据的改变和操 作。
- 副作用详解
- 还使用了注解
@FunctionalInterface
何谓@FunctionalInterface
?
- 点开源码瞧一瞧
- 信息收集
- 是一个信息型注解,旨在告诉编译器,这是一个functional interface
functional interfaces有人译为函数式接口
- 函数式接口只能有一个抽象方法
- 函数式接口可以有多个已经实现的默认方法,或者其他类已经实现的方法,如:Object类的toString()
@FunctionalInterface public interface Function { void test();//只有一个抽象方法 default void test1(){ System.out.println(22222); } String toString();//已经被Object实现,该接口继承了它,因为Object是所有类的父类 } 复制代码
- 函数式接口可以通过Lambda表达、方法引用或构造函数引用来实例化接口
- 只要符合函数式接口的定义,无论是否使用注解
@FunctionalInterface
,编译器都可以识别
小结
1、Lambda表达式可以用来实现函数式接口
list.forEach(integer -> { System.out.println(integer);});//一般不需要指明参数类型
//因为List<Integer> 已经足够让编译器推断参数类型了
复制代码
实现了Consumer接口
2、函数式接口只有一个抽象方法,实现了抽象方法也就实现了接口。所以当某个方法的参数是函数式接口时,只要传入方法的实现就可以了,方法的实现可以用Lambda表达式、方法引用(剽窃其他类的方法)。
3、虽然Lambda表达式是函数,但在Java中它是对象,因为它依附于特定的对象类型——函数式接口。因为它实现了对应函数式接口中的一个抽象方法,也可以说它实现了整个接口,Lambda表达式就是接口的实现类
小测试
@FunctionalInterface
public interface Function {
void test();
}
class myTest {
public void FunctionalInter(Function function){
function.test();
System.out.println("参数是函数式接口被实现了");
System.out.println("----------------------");
}
public static void main(String[] args) {
myTest myTest = new myTest();
myTest.FunctionalInter(() -> System.out.println("表达式没有参数"));//间接调用test()
Function functionInterface = () -> System.out.println("直接将表达式赋值给接口,接口就有了实现");
functionInterface.test();//直接调用test()
}
}
复制代码
你可能会好奇
迭代器(Iterator)原理是什么?
方法引用是什么?
简要说明一下
- 格式:
ClassName::Method
复制代码
- 含义
- 以
forEach
为例
list.forEach(System.out::println); 复制代码
- 因为
forEach
的参数是函数式接口Consumer
,里面有抽象方法accept
方法,只要实现了accept
方法就实现了接口Consumer
,任何实现?剽窃System.out
中的println
方法 - 就形成
accept = println
,也就实现了accept,也就实现了Consumer接口
- 以
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END