Java之lamda表达式(函数式接口应用)
lamda表达式:
使用Lamda表达式需要一个重要的实现要求: SAM(Single Abstract Method)
在之前的匿名内部类中存在一个问题:
IMessage msg = new IMessage(){ // 匿名内部类 public void send(String str){ System.out.println(str); } };
以上代码仅需要一个功能就是:
System.out.println(str);
但是却使用了完整的面向对象结构来表达;
那么为了简化这种结构,就引出了Lamda表达式:
public class Main { public static void main(String[] args) { IMessage msg = (str) ->{ System.out.println(str); }; msg.send("I am here!Lamda!"); } }
在下面的接口中只有一个send()方法,除此之外没有其它任何方法,所以这种接口就被称为函数式接口。
而只有函数式的接口才能被Lamda表达式接受。
@FunctionalInterface // 函数式接口 public interface IMessage { public void send(String str); public static IMessage getInstance(){ return new IMessage() { //静态的匿名内部类 @Override public void send(String str) { System.out.println(str); } }; } }
函数式接口中的abstract方法永远只能有一个,其后可以增加default、static的普通方法。
@FunctionalInterface // 函数式接口 public interface IMessage { public void send(String str); public default void sub(){ System.out.println("jianfa"); } public static void sum(){ System.out.println("jiafa "); } public static IMessage getInstance(){ return new IMessage() { //静态的匿名内部类 @Override public void send(String str) { System.out.println(str); } }; } }
Lamda表达式格式:
- 方法没有参数:() -> {};
- 方法有参数: (参数,参数) -> {};
- 如果现在只有一行语句返回:(参数,参数) -> 返回语句;
方法的引用:
相当于将某个类的方法使用另一个名称表示,并传入对应的参数,方法的功能都是一样。
存在四种格式:
- 引用静态方法:类名称 :: static方法
- 引用某个实例对象方法:实例化对象 :: 普通方法
- 引用特定类型的方法:特定类 :: 普通方法
- 引用构造方法:类名称 :: new
以泛型定义方法的格式应用函数式接口:
@FunctionalInterface public interface IFunction{ // R是返回值类型,P是参数 public R 转换 (P p) ; // R定义返回值类型,P定义参数 }
@FunctionalInterface public interface IFunctions{ // R是返回值类型 public R upper () ; }
package Demo_1_28_以泛型定义方法的格式应用函数式接口; public interface IFunctionss{//P是参数类型 public int compare(P p1,P p2); }
package Demo_1_28_以泛型定义方法的格式应用函数式接口; public interface IFunctionsss{ public R create(String s, int a); }
package Demo_1_28_以泛型定义方法的格式应用函数式接口; public class Main { public static void main(String[] args) { // :: 之前是返回值类型,:: 之后是某种方法,valueOf是static方法 IFunctionfun = String :: valueOf; // 两个参数,返回值是字符串,参数是Integer String str = fun.转换(100); //此时转换方法和valueOf是同一个方法 System.out.println(str.length()); // toUpperCase需要实例化对象才能使用,"www.baidu.com"就是一个字符串对象。 IFunctions fun1 = "www.baidu.com" :: toUpperCase; // 返回支付串, System.out.println(fun1.upper()); //此时upper方法和toUpperCase是同一个方法 // 引用指定类的方法 IFunctionss fun2 = String :: compareTo; System.out.println(fun2.compare("A","a")); //此时compare方法和compareTo是同一个方法 // 引用构造方法 IFunctionsss fun3 = Person :: new; System.out.println(fun3.create("张三",19)); //此时create方法和Person的构造方法是同一个方法 } }
方法引用并不是替代品,只是弥补了此项功能的不足,多出一种选择。
内建的函数式接口:
在系统之中专门提供有一个java.util.function的开发包,可以直接进行函数式接口的使用:
- 功能性函数式接口:接口都是以Function为后缀
接口定义 | 接口使用 |
@FunctionalInterface public interface Function<T,R> { public R apply (T t) ; } |
import java.util.function.Function; public class Main { public static void main(String[] args) { Function |
- 消费型函数式接口:只能够进行数据的处理操作,而没有任何的返回:
· 在进行系统数据输出的时候使用System.out.println();
接口定义 | 接口使用 |
|
import java.util.function.Consumer; public class Main { public static void main(String[] args) { Consumer } }
|
- 供给型函数式接口:
· 在String类中提供了转先写的方法,这个方法没有接收参数,但是有返回值。
|- 方法: public String toLowerCase();
接口定义 | 接口使用 |
@FunctionalInterface public interface Supplier |
import java.util.function.Supplier; public class Main { public static void main(String[] args) { Supplier |
- 断言型函数式接口:进行判断处理
· 在String类中有一个方法是equalsIgnoreCase()方法;
接口定义 | 接口使用 |
@FunctionalInterface public interface Predicate |
import java.util.function.Predicate; public class Main { public static void main(String[] args) { // 断言型函数式接口 Predicate |
如果JDk提供的函数式接口已经满足我们的需求,那么就没有必要重写定义了。