javaSE 笔记 接口中的默认/静态/私有方法 + 方法引用符 + 函数式接口 + 4种函数式接口
接口组成更新概述
接口的组成:
1.常量 public static final
2.抽象方法 public abstract
3.默认方法(java8)
4.静态方法(java8)
5.私有方法(java9)
接口中的默认方法
这是在jdk8中新添加的,因为如果我需要在接口中添加新的抽象方法,那么我的实现类就必须重写这个类的新添加的抽象方法,如果实现类很多,这样就会很麻烦。不过这样也有另一种解决办法,就是定义一个新接口,然后让他继承自原来的接口,在这个新接口中添加新的抽象方法,这样的话旧方法,新方法都能用,但是这样还是有问题,以后每次添加新功能,就得再实现一个新的接口,就是上面说的,这样就添加了一种新的关系,如果以后接口比较多的话,整个体系就会越来越复杂,不利于扩展。
默认方法的定义格式:
public default 返回值类型 方法名(参数列表){ }
public default void show3() { },public是可以省略的
而且注意到,这个默认方法是可以添加方法体的。并且同样是可以被重写的,不过重写的时候不要加上那个default,直接public void show3()即可
接口中静态方法
public static 返回值类型 方法名(参数列表){}
public static void show() { }
接口中的静态方法只能被接口调用,因为如果一个类实现了两种接口,但是两种接口中都有抽象方法test(),如果用实现类名.test(),对象名.test()调用,那么系统是不知道到底调用哪一个接口中的抽象方法的,所以只由接口.test()调用的话,就很清晰了
接口中的私有方法
因为jdk8中定义了默认方法和静态方法,如果两个默认方法和静态方法中的方法体包含了相同的代码实现,那么程序必然考虑将这段实现代码抽取成一个共性方法,而且这个共性方法不需要让别人使用,因此用私有给隐藏起来,就构成了java9的私有方法
private 返回值类型 方法名(参数列表) { }
private void show() { }
private static 返回值类型 方法名(参数列表) { }
private static void method() { }
写的过程中注意默认方法只能调用私有的静态方法和非静态方法,而静态方法只能调用私有的静态方法
方法引用

说是默认会将上面的 s 传给下面的println方法,这边的引用感觉可以理解为重复使用,下面调用的方法,若是具体展开,和上面是完全一样的,所以说这样省略写,编译器是能够看得懂的
方法引用符
:: 改符号被称为引用运算符

引用类方法
引用类方法,其实就是引用类的静态方法
类名::静态方法
Integer::parseInt
eg:
// Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数
useConverter(s -> Integer.parseInt(s));
useConverter(Integer::parseInt); // 类指Integer,方法指parseInt
引用对象的实例方法
其实就是引用类中的成员方法,具体例子看黑马视频P370,讲一下大概,就是在Lambda表达式中定义了一个方法,但是这个方法在另一个类中已经有了对应的成员方法实现了相同的功能所以,我们可以在后续的代码中,引用那个类的成员方法。那么就需要先创建一个该类的对象,然后通过对象调用那个成员方法,eg:
// Lambda表达式被对象实例方法替代的时候,它的形式参数全部传递给该方法作为参数
usePrinter(s -> System.out.println(s.toUpperCase));
// 引用对象的实例方法
PrintString ps = new PrintString();
usePrinter(ps::printUpper); // 这里的printUpper就是跟上面的Lambda表达式的内容一样的,先转大写,再打印出来
引用类的实例方法
其实就是引用类中的成员方法
类名::成员方法
String::substring // 这个例子,这个方法是截取字符串
eg:
第一个参数作为调用者
// Lambda表达式被类的实例方法替代的时候,它的第一个参数作为调用者,后面的参数全部传递给该方法作为参数
useMyString((s,x,y) -> s.substring(x,y));
useMyString(String::substring);
引用构造器
其实就是引用构造方法
类名::new
Student::new
// Lambda表达式被构造器替代的时候,它的形式参数全部传递给该方法作为参数
useStudentBuilder((name,age) -> new Student(name,age));
// 引用构造器
useStudentBuilder(Student::new)
函数式接口
函数式接口:有且仅有一个抽象方法的接口
函数式接口作为局部变量来使用时,eg:
MyInterface my = () -> System.out.println("函数式接口");
my.show();
想要确保一个接口是函数式接口,可以加上一个注解,即 @FunctionalInterface,放在接口定义上方
函数式接口作为方法的参数
无非就是将Lambda表达式当成一个实现了接口的类的对象而已,然后把这个对象作为方法的参数。而且这个方法的参数是一个函数式接口象征着多态的使,这边不写例子的话,跟前面的Lambda表达式练习中的例子是差不多的
包括前面那么多引用各种xxx,那些例子也都是将函数是借口作为方法的参数在使用啊,好像确实是这样的
函数式接口作为方法的返回值
只要将Lambda表达式看成匿名内部类,将整体视为一个对象返回就好了
常用函数式接口Supplier
public interface Supplier
那么接口中的get方法就会生产什么类型的数据供我们使用。
常用函数式接口之Consumer
消费型接口,消费的数据类型由泛型指定
主要方法有 void accept(T t) 对给定的参数执行此操作。
default Consumer
eg: con1.andThen(con2).accept(str)
这边消费的意思好像是只使用数据,但是不会返回什么数据。。
这边还有一个例子,定义一个方法,用不同的方式消费同一个字符串数据两次,用到了andThen方法,看P378
Predict接口,表示一个参数的谓词(布尔值类型)
常用方法:boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现,下面的都是预定义的),返回一个布尔值
default Predict
default Predict
eg: pre1.and(pre2).test(s) ,or方法同理,其实相当于下面的代码
boolean b1 = pre1.test(s);
boolean b2 = pre2.test(s);
boolean b = b1 && b2;
return b;
default Predict
Predict
Function接口
public interface Function<T,R> 表示接受一个参数并产生结果的函数
常用方法两个: R apply(T t) 将此函数应用于给定的参数
default
这个与上面Consumer的andThen有个重要的区别,就是他是顺序执行的,上面那个是走了个分支,不过这个顺序执行下去要保证第一个方法输出的类型与第二个方法输入的类型相同
Function <T,R> 接口通常用于参数处理,转换(Lambda实现),然后返回一个新的值

浙公网安备 33010602011771号