Java8新特性(一)—— Lambda表达式
Lambda表达式:弥补了缺失的函数式编程特点,使函数可以作为参数传给其他函数,同时简化了某些匿名内部类的写法。
匿名内部类:没有名字的类,适用于只需要使用一次的类。必须继承于类或实现相应接口。
- 一般形式:
new 父类构造器/需要实现的接口( ){
重写抽象方法
}
举例:
public abstract class Bird {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract int fly();
}
public class Test {
public void test(Bird bird){
System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");
}
public static void main(String[] args) {
Test test = new Test();
test.test(new Bird() {
public int fly() {
return 10000;
}
public String getName() {
return "大雁";
}
});
}
}
此例中,test方法需要一个Bird类型的参数,而Bird作为一个抽象类是无法直接创建对象的,必须现有实现类才能创建出来Bird类型的实例。这里使用了匿名内部类创建一个Bird实例。匿名内部类没有自己的名称,必须实现它的抽象父类或者接口里面所有的抽象方法。
Java8中对匿名内部类的规则也进行了一些更新,java8之前被匿名内部类访问的局部变量必须手动用final修饰,从java8开始,被匿名内部类访问的局部变量可以不显式用final修饰。如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final修饰。
Lambda表达式可以简化匿名内部类的写法, 但要求被简写的是有且只有一个抽象方法的接口(函数式接口),并且可以通过类型推断机制使编译器推断出表达式类型,不需要显示指明。例如:
interface Bird {
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// }
int fly();
}
public class Test {
public void test(Bird bird) {
System.out.println("能够飞 " + bird.fly() + "米");
}
public static void main(String[] args) {
Test test = new Test();
test.test(() -> 10000);
// test.test(new Bird() {
//
// public int fly() {
// return 10000;
// }
//
// public String getName() {
// return "大雁";
// }
// });
}
}
打印结果:
由此可以看出lambda表达式的写法如下:
写法:(argument) → (body)
结构:
- 参数:可以有零个或多个;参数类型可以声明也可以根据上下文判断(遇到不能判断的场景必须声明);所有参数需包含在圆括号内,参数之间用逗号分隔;没有参数时,需使用一个圆括号(例如: ()->42);当只有一个参数,且类型可推导时,圆括号可以省略(例如:i ->return i * i)。
- 语句:可以包含,零到多条语句;只有一条语句时花括号可以省略;函数的返回类型与该主体表达式一致;如果包含一条或多条语句,则表达式必须包含在花括号中。
上面的例子就是没有参数且只有一条语句的例子,也可以使用多个参数,包含多个语句,举例如下:
- 有一个参数:
interface Bird {
int fly(String birdName);
}
public class Test {
public void test(Bird bird) {
System.out.println("能够飞 " + bird.fly("bird") + "米");
}
public static void main(String[] args) {
Test test = new Test();
test.test((String birdName) -> birdName.length());
}
}
打印结果:
此例中,方法传入一个String类型作为参数,而birdName.length是方法的返回。该方法仍然实现Bird类中的fly方法,最后返回的数值是“bird”的长度,为4。
- 有多个参数:
interface Bird {
int getNameLength(String birdName1, String birdName2);
}
public class Test {
public void test(Bird bird) {
System.out.println("名字总长度 " + bird.getNameLength("Hawk", "eagle"));
}
public static void main(String[] args) {
Test test = new Test();
test.test((birdName1, birdName2) ->
{
int length1 = birdName1.length();
int length2 = birdName2.length();
return length1 + length2;
});
}
}
打印结果:
与上个例子类似,此例中方法使用两个参数,最后返回两个名字的总长度。
一些常见方法的简写:
- 线程的创建:
new Thread(new Runnable(){// 接口名
@Override
public void run(){// 方法名
System.out.println("Thread run()");
}
}).start();
简化为:
// JDK8 Lambda表达式写法
new Thread(
() -> System.out.println("Thread run()")// 省略接口名和方法名
).start();
- 比较器的简写:
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, new Comparator<String>(){// 接口名
@Override
public int compare(String s1, String s2){// 方法名
if(s1 == null)
return -1;
if(s2 == null)
return 1;
return s1.length()-s2.length();
}
});
简化为:
// JDK8 Lambda表达式写法
List<String> list = Arrays.asList("I", "love", "you", "too");
Collections.sort(list, (s1, s2) ->{// 省略参数表的类型
if(s1 == null)
return -1;
if(s2 == null)
return 1;
return s1.length()-s2.length();
});
- 点赞
- 收藏
- 关注作者
评论(0)