Lambda表达式描述的是,接口中那个抽象方法要做的事情。
实际Lambda本质是,实现了那个接口的一个类的对象。
常量:默认是 public static final
方法:默认是 public abstract
在JAVA8中,增加了默认方法(public default),静态方法(public static)
在JAVA9中,增加了私有方法
public interface eatable {
// 抽象方法 实现类 必须进行实现
void funAbstract();
// 默认方法 和 静态方法 都需要方法体
/**
* 默认方法: 不强制实现类必须重写, 实现类可以直接使用
* 主要用于接口的升级,而不破坏现有的代码
*/
default void funDefault(){
System.out.println("默认方法");
}
/**
* 接口中的静态方法 只能被接口调用
*/
static void funStatic(){
System.out.println("静态方法");
}
}
public static void main(String[] args) {
// 实现 抽象方法 并调用 默认方法
((eatable) () -> System.out.println("实现抽象方法")).funDefault();
// 实现 抽象方法 并调用 抽象方法
((eatable) () -> System.out.println("实现抽象方法")).funAbstract();
// 接口中的静态方法 只能被 接口调用, 不能被实现类调用
eatable.funStatic(); // OK
((eatable) () -> System.out.println("实现抽象方法")).funStatic(); // Error
}
引用 类中的 静态方法
// 抽象方法的参数 全部传递给 被引用的静态方法
public static void main(String[] args) {
((eatable) s -> Integer.parseInt(s)) // lambda 形式
.toInt("2349645");
((eatable) Integer::parseInt) // 类名::静态方法
.toInt("23");
}
interface eatable {
void toInt(String s);
}
引用 类中的 非静态方法
// 抽象方法的参数 全部传递给 被引用的非静态方法
public static void main(String[] args) {
((eatable)s -> System.out.println(s.toUpperCase()))
.toUpper("fdf");
((eatable)new linshi()::printString)
.toUpper("fsdf"); // 借助对象 , 引用类中的非静态方法
}
class linshi {
public void printString(String s){
System.out.println(s.toUpperCase());
}
}
interface eatable {
void toUpper(String s);
}
也可以这样:
但注意:接口中的那个抽象方法 第一个参数的参数类型 得是 linshi,后面的参数传给了 printString 方法。
public static void main(String[] args) {
((eatable)(s,a) -> System.out.println(a.toUpperCase()))
.toUpper(new linshi(),"fgwerg");
/**
* 使用这种 类名::非静态方法 形式的时候
*
* 注意 接口中的那个抽象方法 第一个参数的参数类型 得是 linshi
* 之后的参数 都传给 printString 方法
*/
((eatable)linshi::printString)
.toUpper(new linshi(),"grg");
}
class linshi {
public void printString(String s){
System.out.println(s.toUpperCase());
}
}
interface eatable { // 第一个参数 作为调用者
void toUpper(linshi a,String s); // 第二个参数 给到 printString 方法去作为参数
}
有且仅有一个抽象方法的接口,函数式接口就是 lambda 表达式的使用前提。
可以使用 @FunctionalInterface 进行标记 函数式接口。
使用函数式接口 作为参数时,可以传递过去一个 lambda 表达式。
public class lambdademo {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>();
array.add("ccc");
array.add("aa");
array.add("b");
array.add("dddd");
System.out.println("排序前: " + array);
// Collections.sort(array); // 自然排序
Collections.sort(array,getComparator()); // 比较器排序
System.out.println("排序后: " + array);
}
private static Comparator<String> getComparator(){
// 匿名内部类方式
// return new Comparator<String>() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length() - s2.length();
// }
// };
// lambda方式, 因为返回值是 函数式接口
return (s1,s2) -> s1.length() - s2.length();
}
}
Supplier接口
public static void main(String[] args) {
// 传一个 lambda ,实际上是 定义 抽象方法Supplier.get的逻辑
String string = getString(() -> "林青霞");
System.out.println(string);
}
// 这里设置接口泛型 为 String, 表示 get 方法 返回类型是 String
private static String getString(Supplier<String> sup){
return sup.get();
}
Consumer接口
public static void main(String[] args) {
// 第一个参数是 传过去的数据
// 第二个参数是 定义 抽象方法 accept的逻辑
getString("随便吧",System.out::print);
}
// 泛型 String 指定了 accept 的参数类型
private static void getString(String s, Consumer<String> cn){
// cn.accept(s);
Consumer<String> t = a -> System.out.print(a.length() + 1);
cn.andThen(t).accept(s);
// cn先执行一次 accept(s)
// t 再执行一次 accept(s)
}
Predicate接口
常用于判断参数是否满足指定条件
boolean test(T t) // 对给定参数进行判断, 判断逻辑由 lambda 提供
default Predicate<T> negate()
default Predicate<T> and(Predicate other)
default Predicate<T> or(Predicate other)
public static void main(String[] args) {
boolean res = checkString("fewef", s -> s.length() > 8);
System.out.print(res);
}
private static boolean checkString(String s, Predicate<String> t){
// return t.test(s);
// return t.negate().test(s); // 非
// return t.and(a -> a.startsWith("fy")).test(s); // 与
return t.or(a -> a.startsWith("fy")).test(s); // 或
}