今天是高考的日子,是大四师兄师姐答辩毕业的日子。一代又来,一代又去。好久没写博客,借此特殊日子整理一下前不久学java8新特性时写的代码,留下痕迹。(本博客的代码根据 java8新特性教程 学习整理,加上个人的理解而成,关于某个新特性的介绍代码里的注释已经阐述清楚,故不再写文字介绍,直接看代码吧!)
本篇介绍java8的新特性之一:lambda表达式。
1.先定义两个功能性接口IConvert和IFormula,以作测试用:
接口IConvert:
/**
* 功能性接口
*/
@FunctionalInterface
interface IConvert<F,T>{
//将F类型转换成T类型
T convert(F from);
default void intValue2(){
}
default void intValue3(){
}
}
接口IFormula:
/**
接口的默认方法
Java8允许开发者通过使用关键字 default 向接口中加入非抽象方法。
这一新的特性被称之为扩展方法。
*/
public interface IFormula{
double calculate(int num);
//扩展方法
default double sqrt(int a){
return Math.sqrt(a);
}
}
2. 使用lambda表达式:
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.Test;
/*
* 为什么lambda表示式可以这样随意的使用?
* 每个lambda表达式都对应一个指定的类型,这个指定的类型是由接口确定的。该接口被称之为功能性接口,
* 它必须且恰好只包含一个抽象方法声明。被指定接口类型所对应的lambda表达式刚好和这个接口的抽象方法相匹配。
* 因为默认方法不是抽象的,因此可以在功能性接口中添加多个默认方法。
*
* 为了确保定义的接口达到要求,可以在接口上添加@FunctionalInterface注解。
* 编译器可以检测到该注解并判断你的接口是否满足条件,如果定义的接口包含多个抽象方法时,编译器便会报错。
*
*/
public class LambdaExpression {
@Test
public void testComparator(){
List<String> names = Arrays.asList("peter222", "anna3334444", "mike22442", "xenia");
//旧的写法
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
System.err.println(names);
//[xenia, peter222, mike22442, anna3334444]
//lambda写法
Collections.sort(names, (s1, s2) -> s1.length() - s2.length());
System.err.println(names);
}
@Test
public void testIConvert(){
IConvert<String, Integer> convertor = (from) -> ( Integer.parseInt(from));
int converted = convertor.convert("123");
System.err.println(converted);
}
/**
* lambda范围 : 访问本地变量
*/
@Test
public void nativeVariable(){
//和匿名变量不同的是变量num不必强制的被声明为final。
//实际上,变量num在编译期是被隐式的转换为fianl类型的。
//final int num = 1;
int num = 1;
IConvert<Integer, String> converter =
(from) -> String.valueOf(from+num);
String s = converter.convert(123);
System.err.println(s);// 124
}
static int outerStaticNum = 11;
int outerNum = 22;
/**
* lambda范围 : 访问对象字段和静态变量
*/
@Test
public void visit_ObjectField_StaticVariable(){
//和访问本地变量相反,我们在lambda表达式里即可以读取也可以写入对象字段和静态变量.
//这一准则同样适用于匿名类。
IConvert<Integer, String> stringConverter1 = (from) -> {
outerNum = 23;
return String.valueOf(from);
};
System.err.println(stringConverter1.convert(outerNum)); // 22
IConvert<Integer, String> stringConverter2 = (from) -> {
outerStaticNum = 72;
return String.valueOf(from);
};
System.err.println(stringConverter2.convert(outerStaticNum)); // 11
}
/**
* lambda范围 : 不能访问接口默认方法
*/
@Test
public void visitInterfaceDefaultMethod(){
//默认方法不能被lambda表示式内部的代码访问。下面的代码不能通过编译:
//IFormula formula = (num) -> sqrt(num*100);
// err : The method sqrt(int) is undefined for the type LambdaExpression
}
public static void testRun(String[] args)
{
runPast();
runNow();
Runnable r = () -> { System.out.println("Runnable.........."); };
new Thread(r).start();
}
public static void runPast()
{
new Thread(new Runnable()
{
@Override
public void run()
{
System.out.println("以前的实现");
}
}).start();
}
/**
* Lambda表达式写法
* 函数式接口,Java 8引入了@FunctionalInterface注解来表明一个接口为一个函数式接口,函数式接口就是只包含一个抽象方法的接口。
*/
public static void runNow()
{
new Thread( () -> {
System.out.println("my lambda!");
} ).start();
}
}
详情请见这篇博客: java8新特性教程