接口的变化:接口中的方法可以有实现
1.接口中可以有静态方法,可以通过 接口名.方法名 调用。(通常会把返回接口对象的方法放到接口里)
2.接口中可以有默认方法,这类方法为公开的(public)方法,但要加上 default 修饰符,接口的实现类会默认继承此方法,若一个类实现了两个具有相同默认方法的接口,类中必须要对该默认方法进行覆盖,调用此方法的格式为: 接口名.super.方法名();
Lambda
语法:
(参数表)->{方法实现}
(参数表)->表达式 等价于 return 表达式;
(参数表)->单句实现 (return 语句不能视为单句实现)
注意:参数类型可以省略, 单参函数 可以省略括号;实现的接口必须是函数式接口
示例:
(Student s)->{return s.getAge()>18;} (Student s)->s.getAge()>18 (s)->s.getAge()>18 s->s.getAge()>18
函数式接口:只有一个抽象方法的接口
常见函数式接口:
接口 | 函数描述符 | 方法名 |
---|---|---|
Predicate<T> 谓词 | T->boolean | test |
Consumer<T> 消费者 | T->void | accept |
Function<T,R> 函数 | T->R | apply |
Supplier<T> 提供者 | ()->T | get |
BiPredicate<T,R> | (T,R)->boolean | test |
BiConsumer<T,R> | (T,R)->void | accept |
BiFunction<T,U,R> | (T,U)->R | apply |
UnaryOperator<T> | T->T | apply |
BinaryOperator<T> | (T,T)->T | apply |
方法引用
进一步简化接口对象的创建及使用,向函数式编程靠近,使程序员的代码更简单,更直接,更直白,只需提供关键的数据及逻辑,其他靠编译器推理
类型 | Lambda | 方法引用 |
---|---|---|
参数方法 | (A arg0, B rest)->arg0.method(rest) | A::method |
静态方法 | (args)->ClassName.method(args) | ClassName::method |
其他对象方法 | (args)->expr.method(args) | expr::method |
构造方法 | ()->new Student() | Student::new |
构造方法 | (String s)->new Student(s) | Student::new |
参数化
开闭原则: 对扩展开放,对修改关闭
通过一段通用的代码,将某功能差异部分定义成参数。参数表示了代码中可能变化的部分。运行时,参数接收到确切的值,保证代码的正常运行。
参数化的好处:提升共性代码的可重用性
结论:可以将代码中不能确定(变化的)部分,定义成参数
行为参数化:进一步提高代码可用性
代码中差异部分可能又是一段代码,需要使用参数表示差异部分的代码。
在java中只能通过接口定义代码参数(行为参数)
Runnable r1=new Runnable(){ public void run(){ System.out.println("匿名内部类"); } }; Runnable r2=()->{ System.out.println("lambda"); }; //方法引用 Arrays.asList("a","o","e").forEach(System.out::print);
lambda可以认为是一种特殊的匿名内部类
1 lambda形参类型通常可以省略,但注意不要有歧义
2 如果lambda形参个数只有1个,且省略了形参类型 ,同时()也可以省略
3 如果lambda{}中只有一个语句,{}可以省略;
注意:如果{}省略后,唯一的语句有return;那么return必须省略
lambda和匿名内部类的区别
1 匿名内部类可以用于实现任意类型的接口
lambda只能实现只有1个抽象方法的接口(函数接口)
2 匿名内部类中this表示匿名内部类对象本身
lambda中this表示外部类对象