什么是Lambda?Lambda是λ,希腊字母表中排序第十一位的字母。当你在使用IDEA书写Lambda表达式的时候,左侧会有λ的提示:,它也是java8的新特性:不再使用传统的匿名对象的方式,而使用其更为简洁的语法。那么具体应该怎么使用呢
第一个Lambda表达式
我们先看看什么是Lambda表达式。举一个最简单的例子我们一般写点击事件是这样的
button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {}
});
一个点击事件写了这么多行,都不知道重点是什么,这样就凸显Lambda简洁的优势了
button.setOnClickListener(v -> {});
如果是第一次接触到Lambda,恐怕会丈二和尚摸不着头脑,我们这边简单的解释一下:这里的v就是上面onClick中的View对象,大括号中的就是主体部分,他们之间用->分开
辨别Lambda表达式
除了刚才演示的表现形式以外,还有多种变体,我们简单的举几个例子
- .不包含参数,并且返回值为void
new Thread(()->{}).start();
- .之前演示的,一个参数,并且主体为一个表达式
button.setOnClickListener(v -> Log.d("tag", "click"));
- 一个参数,并且主体为一段代码块。只有一行代码的表达式可以使用大括号也可以不使用,但是一段代码块的话就一定要使用大括号
button.setOnClickListener(v -> {
Log.d("tag", "click");
Log.d("tag", "click");
}
});
- 多个参数的方法,你既可以显示声明变量参数类型,也可以啥都不写依靠编译器推断得出。如果显示声明,那么就需要用括号将参数括起来
listview.setOnitemClickListener((parent, view, position, id) -> {})
listview.setOnitemClickListener((AdapterView> parent, View view, int position, long id) -> {})
这两种写法是等价的
函数式接口
函数接口是只有一个抽象方法的接口,这点一定要搞清楚,只有符合上述条件,才可以用作Lambda表达式类型,2个3个抽象方法的接口是不能玩的首先列举以下6种常见的函数式接口
接口 | 参数 | 返回类型 |
---|---|---|
Function |
T | R |
Predicate |
T | boolean |
Supplier |
None | T |
UnaryOperator |
T | T |
Consumer |
T | void |
BinaryOperator |
(T, T) | T |
OK,我看第一遍的时候愣是看不懂这个里面想传达的意思,然后写着写着才明白,依然举例我们使用Function来说明。
Function function3=
integer -> ""+integer;System.out.println(function3.apply(111));
这个方法的目的在于将Integer转成String。入参泛型为Integer,返回值泛型为String。OK看不明白不要紧,我们转成常见的方式来看,写一个Integer转String的接口,我们会定义成这种形式
public interface ConvertListener {
String convert(Integer integer);
}
ConvertListener convertListener1=new ConvertListener() {
@Override public String convert(Integer integer) {
return ""+integer;
}
};
convertListener1.convert(111);
OK,就是这么简单
方法与构造函数引用
如果方法体只是简单的函数引用,则可以直接使用::,这样可以让我们的代码更加简洁。看一个例子:
Function function2=String::valueOf;function2.apply(3);
::左边的对象调用符号右边的方法
这里我只是想简单说明一下,因为这段代码完全不能体现他的优越性
现在我们开始展开演示首先是一个ConvertClass类
public class ConvertClass {
public String startsWith(Integer integer) {
return String.valueOf(integer);
}
public static String startsStaticWith(Integer integer) {
return String.valueOf(integer);
}
}
- Lambda访问构造方法
我们得再定义一个抽象接口以使用ConvertClass的构造方法
@FunctionalInterfaceinterface
ConvertClassFactory {
T create();
}
再次强调ConvertClassFactory只能有一个抽象方法
最后看看如何使用
ConvertClassFactory factory=ConvertClass::new;
ConvertClass convertClass=factory.create();
通过"类名::new"的方式获得构造的引用,最后通过create调用构造方法,编译系统会自动识别调用ConvertClass的哪个构造方法。
- Lambda访问静态方法
刚才我们已经拿到了ConvertClass的对象convertClass,下面我们来看看如何调用静态方法startsStaticWith
ConvertListener listener2=ConvertClass::startsStaticWith;
String re2=listener2.convert(101);
System.out.println(re2);
直接就是类::方法名直接使用即可
- Lambda访问对象的方法
ConvertListener listener=convertClass::startsWith;
String re1=listener.convert(100);
System.out.println(re1);
其实区别并不大,主要是用已生成的对象去直接调用方法而已
Lambda访问外部局部变量
还记得我们在setOnItemClickListener里面如果遇到内部类使用position时,前面要加一个final来修饰?在Lambda中,这个final可以被省略,但是你依然不可以为了赋值,它实际上依然是final
参考链接
JAVA8中L�ambda和S�tream
Java 8 Lambda表达式