文章目录
-
-
- 接口默认实现
- 函数式接口
- Lambda 表达式
- 双冒号`::`
-
接口默认实现
若要修改接口,比如给接口添加一个抽象方法,那就得修改所有实现了该接口的实现类;麻烦!
接口里面可以有默认实现,就是在方法声明上使用default关键字,实现这个接口的类,可以不再实现这个默认实现的方法了;
interface A{
default String getName(){
return "zxj";}public abstract show();
}
默认方法冲突:
1、若一个接口B继承自另一个接口A,两个接口中有同样的默认实现方法,那么只保留父接口中的默认方法;
2、若一个类实现两个接口,两个接口有相同的方法,一个接口默认实现了这个方法,那么另一个方法不管是默认实现,还是让它以抽象方法的形式存在,编译都会报错,我们需要在实现类上重写接口的默认方法,或实现抽象方法;
3、一个类继承了类A、实现的接口B,父类A中有一个方法和接口B中的默认实现方法冲突了,根据类优先原则,会使用父类的方法;
函数式接口
函数式接口有且只有一个抽象方法,接口定义上使用@FunctionalInterface
注解来标注接口只有一个抽象方法;
Function/BiFunction
、Consumer/BiConsumer
Bi**
方法里面接收两个参数,第一个参数是用来接收对象实例的,使用对象实例调用第二个参数的非静态方法;
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u); // T接收的是对象
}
Lambda 表达式
Lambda表达式,也称为闭包,允许把函数作为一个方法的参数进行传递;
lambda表达式需要用一个接口类型的引用来接收,Lambda表达式方法体其实就是函数式接口的实现;然后将接口类型的引用作为参数传入方法;
语法格式:函数式接口类型的引用 = (参数) -> 表达式
或 (参数) -> {代码块}
(参数是函数式接口里面的方法的参数;)
- 可选类型声明:不用声明参数的类型;
- 可选参数圆括号:参数是一个的时候不用写圆括号,参数有多个的时候,要加上圆括号;不需要传参的时候直接写一对小括号;
- 可选大括号:主体只有一个语句,不用使用大括号,主体有多条语句,需要使用大括号括起来;
- 可选返回关键字:若主体只有一个表达式语句,没有使用大括号,则不需要写返回值,编译器会自动返回;若使用了大括号,需要指定表达式返回了一个数值;
Lambda表达式可以替代内部类;
public class Test {
public static void main(String[] args) {
runThreadByLambda();runThreadByInnerClass();}public static void runThreadByLambda() {
// Runnable就是一个函数式接口:他只有一个方法run()方法。// 1、因为run()方法没有参数,所以 ->前面的()中不需要声明形参;// 2、run返回的是void,所以不需要return;// 3、->后面写的代码其实就是定义在run方法内的代码;因为此处代码只有一行,所以{}也可以省略;Runnable runnable = () -> System.out.println("这个是用Lambda表达式实现的线程");new Thread(runnable).start(); // 将引用变量runnable作为参数传入方法;}public static void runThreadByInnerClass() {
Runnable runnable = new Runnable() {
// 匿名内部类;@Overridepublic void run() {
System.out.println("这个是用内部类实现的线程");}};new Thread(runnable).start();}
}
双冒号::
Lambda表达式的简写形式:引用的方法,就是Lambda表达式的方法体实现;
闭包:就是能够读取函数内部变量的函数,可以理解为一个函数内部的函数,它是函数内部与函数外部连接的桥梁;
Java中的闭包有:内部类、局部内部类、匿名内部类;
类名::方法名
,相当于对这个方法闭包的引用;使用双冒号可以访问类的构造方法、普通方法、静态方法;
(1)需要创建一个接口来接收这个引用;这个接口有且只有一个抽象方法,使用@FunctionalInterface
注解来标注接口只有一个抽象方法;
@FunctionalInterface
interface MyConvert1<F, T>{
T convert(F form);
}
@FunctionalInterface
interface MyConvert2<T>{
void convert(F form);
}
也可以使用Java8新提供的函数式接口Function/BiFunction、Consumer/BiConsumer;
public class Test {
public static void main(String args[]) throws Exception {
Consumer<String> printStrConsumer = DoubleColon::printStr;printStrConsumer.accept("printStrConsumer");Consumer<DoubleColon> toUpperConsumer = DoubleColon::toUpper;toUpperConsumer.accept(new DoubleColon());BiConsumer<DoubleColon, String> toLowerConsumer = DoubleColon::toLower;toLowerConsumer.accept(new DoubleColon(), "toLowerConsumer");BiFunction<DoubleColon, String, Integer> toIntFunction = DoubleColon::toInt;int i = toIntFunction.apply(new DoubleColon(), "toInt");}
}
class DoubleColon {
public static void printStr(String str) {
System.out.println("static : " + str);}public void toUpper() {
System.out.println("toUpper : " + this.toString());}public void toLower(String str) {
System.out.println("toLower : " + str);}public int toInt(String str) {
System.out.println("toInt : " + str);return 1;}
}
一般方法的引用格式:
- 如果是静态方法,则是ClassName::methodName。如 Object ::equals
- 如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
- 构造函数.则是ClassName::new
public class Demo2 {
public static void main(String[] args) {
Runnable runnable = Demo2::run;new Thread(runnable).start();}public static void run(){
System.out.println("方法引用的代码...");}
}
https://blog.csdn.net/qq_35805528/article/details/53264301
Java语法糖系列五:内部类和闭包:https://www.jianshu.com/p/f55b11a4cec2
双冒号:https://blog.csdn.net/xvhongliang/article/details/84311887
https://blog.csdn.net/kegaofei/article/details/80582356