若要修改接口,比如给接口添加一个抽象方法,那就得修改所有实现了该接口的实现类;麻烦!
接口里面可以有默认实现,就是在方法声明上使用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表达式可以替代内部类;
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() { // 匿名内部类;
@Override
public 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;
}
}
一般方法的引用格式:
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