最近在学习和整理Java 8的新特性,做个手头笔记,好让以后自己方便复习。
1. Lambda 表达式:
Lambda表达式的基础语法: ()-> {}
() 为参数列表,可以无參,即不填任何东西;
{} 为函数体;
Lambda表达式使得许多复杂的写法简洁化,主要有以下几个方面:
1.1 匿名内部类
对匿名内部类的优化,最直观的就是对 Runnable中的run方法的改写,先看一下java 8之前的 run()实现
new Runnable() {
public void run() {
System.out.println("inner class implements Runnable interface");
System.out.println("cannot refer variable value, only constant value");
}
}.run();
使用Lambda表达式实现run()
int i=1;
Runnable r=()->{
System.out.println("Lambda implements Runnable interface");
System.out.println("although lambda can refer variable value,"
+ " but still cannot change variable value in Runnable method");
// i++; //---> cannot accept
System.out.println("i="+i);
};
r.run();
以上可以看到使用lambda表达式以后,使得匿名内部类实现更加简洁,同时可以传递方法体外的变量值到run()中,不过要注意的是,方法体中还是不能对变量值进行修改。
1.2 循环
Lambda简化循环表达式
// 系统会自动推断出e的类型
Arrays.asList("a","b","c").forEach(e -> System.out.println(e));
Arrays.asList("aa","bb","cc").forEach((String e) -> System.out.println(e));
Arrays.asList("q","w","e").forEach(e -> {
// 函数体
System.out.println(e);
});
// Lambda可以引用类的成员变量与局部变量(如果这些变量不是Final的话, 它们会被隐含的转为final,这样效率更高)
String separator =",";
Arrays.asList("a","b","c").forEach(e -> System.out.println(e+separator));
1.3 排序
// Lambda 实现排序 Integer[] list = {3,7,2,3,1,10,4,8}; Arrays.stream(list).forEach(e->System.out.print(e+",")); Arrays.asList(list).sort((e1,e2) -> e1.compareTo(e2)); System.out.println(); Arrays.stream(list).forEach(e->System.out.print(e+",")); // 重写compareTo方法
Arrays.asList(list).sort((e1,e2) -> {
if(e1<e2) {
return 1;
}else if(e1 > e2) {
return -1;
}else {
return 0;
}
});
System.out.println();
Arrays.stream(list).forEach(e->System.out.print(e+","));
Arrays.asList(list).sort((e1,e2) -> {
if(e1<e2) {
return 1;
}else if(e1 > e2) {
return -1;
}else {
return 0;
}
});
System.out.println();
Arrays.stream(list).forEach(e->System.out.print(e+","));
使用lambda表达式,对于常规的排序,直接使用compareTo,在lambda的方法体中实现就可以了。如果需要重写compareTo方法,直接在函数体中实现。
2. Lambda_FunctionalInterface
2.1 为什么需要加一个FunctionalInterface Annotation ?
简单来说就是Java8 给这样一类接口定义了统一的类型,即声明了一个方法的接口,这里的方法不包括default 方法和Java.lang.Object 下的public 方法(例如toString(),equals() )这类只声明了一个方法的Interface,给它引入的一个新概念--函数式接口(Functional Interface),引入注解@FunctionalInterface 来标注这类接口。
2.2 Functional Interface 的定义
@FunctionalInterface public interface FunctionalDefaultMethods{ // 有且仅有一个抽象方法,这样这个接口才能作为Functional Interface void method(); // 默认方法可以在 Functional Interface 中 default void defaultMethod() { System.out.println("functional interface default method"); } // java.lang.Object 中的public可以在Funcational Interface中 String toString(); boolean equals(Object o); // clone() 是java.lang.Object中的protected方法,不可以在Functional Interface中 // Object clone(); }
2.3 Lambda表达式调用实现Functional Interface中的方法
一直不明白为什么一定要给接口加上注解Functional Interface,但是有一点是可以明确知道的,加了Functional Interface的接口,Lambda表达式可以直接调用实现对应接口中的方法,让Lambda表达式发挥最大的简便。也许Functional Interface还有其他的作用,之后再探索。
//*******lambda 表达式调用非Functional Interface 方法
// NonFunctionalInterfaceLambda call =()-> {
// System.out.println("非Functional Interface 方法使用Lambda");
// };
// call.testLambdaExpress();
// Error: The target type of this expression must be a functional interface
Error: The target type of this expression must be a functional interface
//*******lambda 表达式调用Functional Interface 方法
FunctionalDefaultMethods call =()-> {
System.out.println("override funcitonal interface method");
};
call.method();
2.4 Functional Interface 中的default 方法
留白。。让我再想想为啥一定要default方法。。
3.Lambda 表达式方法引用