java8 Lambda学习笔记
Lambda由三部分组成
* 1.形参列表。形参列表允许省略形参类型。形参列表只有一个参数,形参列表的圆括号也可以省略
* 2.箭头(->)。必须由英文中画线和大于号组成
* 3.代码块。如果只有一条语句,可以省略代码块的花括号。Lambda代码块只有一条语句,可以省略return关键字
* Lambda表达式需要返回值,而它的代码块中仅有一条省略了return的语句,Lambda表达式会自动返回这条语句的值
*
* Lambda表达式的类型,被称为"目标类型"。目标类型必须是函数式接口(functional interface).
* 函数式接口代表只包含一个抽象方法的接口。函数式接口可以包含多个默认方法,类方法。但只能声明一个抽象方法
* 如果采用匿名内部类语法来创建函数式接口的实例,则只需要实现一个抽象方法。在这种情况下即可采用Lambda表达式来创建对象。
* 该表达式创建出来的对象的目标类型就是这个函数式接口
* 一个函数式接口有且只有一个抽象方法。
* 默认方法不是抽象方法,因为它们已经实现了。
* 重写了超类Object类中任意一个public方法的方法并不算接口中的抽象方法。
*
* Runnable就是函数式接口
* @FunctionalInterface
* 该注解通常放在接口定义前面,该注解对程序功能没有任何作用,它用于告诉编译器执行更严格检查
* 检查该接口必须是一个函数式接口,否则编译器就会报错
* Lambda表达式的结果就是被当成对象,因此程序中完全可以使用Lambda表达式进行赋值
*
* 为保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式。
* 1.将Lambda表达式赋值给函数式接口类型的变量
* 2.将Lambda表达式作为函数式接口类型的参数传给某个方法
* 3.使用函数式接口对Lambda表达式进行强制类型转换
*
* 同样的Lambda表达式的目标类型完全可能是变化的-唯一的要求是,Lambda表达式实现的匿名方法与目标类型(函数式接口)中
* 唯一的抽象方法有相同的形参列表
*
* 如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器引用
* 引用类方法:类名::类方法 函数式接口中被实现方法的全部参数传给该类该方法作为参数
* (a,b,...)->类名.类方法(a,b,...)
* 引用特定对象的实例方法:特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数
* (a,b,...)->特定对象.实例方法(a,b,..)
* 引用某类对象的实例方法:类名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数
* (a,b,...)->a.实例方法(b,...)
* 引用构造器:类名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数 (a,b,...)->new 类名(a,b,...)
import javax.swing.JFrame; interface Eatable{ void taste(); } interface Flyable{ String fly(String weather); } interface Addable{ int add(int a,int b); //int delete(String data); default int delete(String data) { return 0; } } public class LambdaQs { public void eat(Eatable e) { System.out.println(e); e.taste(); } public void drive(Flyable f) { System.out.println("我正在驾驶:"+f); f.fly("【碧空如洗的晴日】"); } public void test(Addable a) { System.out.println("和为:"+a.add(5,3)); } public static void main(String[] args) { LambdaQs lq = new LambdaQs(); lq.eat(new Eatable() { @Override public void taste() { System.out.println("匿名内部类方法"); } }); //Lambda表达式实际上会被当成"任意类型"的对象 //省略花括号 lq.eat(()->System.out.println("今天的水果可以"));//不带形参 //省略形参的圆括号 lq.drive(weather->{//只有一个形参 System.out.println("今天的天气"+weather); System.out.println("飞机平稳飞行"); return "test"; }); //代码块中只有一条语句,即使该表达式需要返回值,也可以省略return关键字 lq.test((a,b)->a+b);//两个形参 /** * 为保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式。 * 1.将Lambda表达式赋值给函数式接口类型的变量 * 2.将Lambda表达式作为函数式接口类型的参数传给某个方法 * 3.使用函数式接口对Lambda表达式进行强制类型转换 */ //Runnable就是函数式接口 /* * new Runnable() { * * @Override public void run() { // TODO Auto-generated method stub } }; */ //@FunctionalInterface //public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ //public abstract void run(); //} Runnable r = ()->{ for(int i=0;i<20;i++) { System.out.println(i); } }; //不是函数式接口 /* * Object obj = () ->{ for(int i=0;i<20;i++) { System.out.println(i); } }; */ /** * 同样的Lambda表达式的目标类型完全可能是变化的-唯一的要求是,Lambda表达式实现的匿名方法与目标类型(函数式接口)中 * 唯一的抽象方法有相同的形参列表 */ //强制类型转换 Object obj =(Runnable) () ->{ for(int i=0;i<20;i++) { System.out.println(i); } }; Object obj2 =(FunctionalIntefaceTest) () ->{ for(int i=0;i<20;i++) { System.out.println(i); } }; //如果Lambda表达式的代码块只有一条代码,还可以在代码块中使用方法引用和构造器引用 //引用类方法:类名::类方法 函数式接口中被实现方法的全部参数传给该类该方法作为参数 // (a,b,...)->类名.类方法(a,b,...) Converter converter1 = from->Integer.valueOf(from); Integer i1 = converter1.converter("89"); System.out.println(i1);//输出89 /** * 方法引用代替Lambda表达式:引用类方法 * 函数式接口中被实现方法的全部参数传给该类方法作为参数 */ Converter converter1_2 = Integer::valueOf; Integer i1_2 = converter1_2.converter("80"); System.out.println(i1_2);//输出80 //引用特定对象的实例方法:特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数 // (a,b,...)->特定对象.实例方法(a,b,..) Converter converter2_1 = from->"fkit.org".indexOf(from); Integer i2 = converter2_1.converter("it"); System.out.println(i2);//2 /** * 方法引用代替Lambda表达式:引用特定对象的实例方法 * 函数式接口中被实现方法的全部参数传给该方法作为参数 */ Converter converter2_2 = "fkit.org"::indexOf; Integer i2_2 = converter2_2.converter("it"); System.out.println(i2_2);//2 //引用某类对象的实例方法:类名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数 //(a,b,...)->a.实例方法(b,...) MyTest mt = (a,b,c)->a.substring(b,c); String str = mt.test("Python I Love You", 2, 10); System.out.println(str); MyTest mt2 = String::substring; String str2 = mt2.test("Python I Love You", 2, 10); System.out.println(str2); //引用构造器:类名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数 (a,b,...)->new 类名(a,b,...) YourTest yt = (String a)->new JFrame(a); JFrame jf = yt.win("我的窗口"); System.out.println(jf); YourTest yt2 = JFrame::new; JFrame jf2 = yt2.win("我的窗口2"); System.out.println(jf2); } }

浙公网安备 33010602011771号