今天是高考的日子,是大四师兄师姐答辩毕业的日子。一代又来,一代又去。好久没写博客,借此特殊日子整理一下前不久学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); } }
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(); } }