1.接口interface
- 新增函数式接口@FunctionalInterface,此接口为函数式接口,只能有一个抽象方法,用于在编译期间检查接口是否符合函数式接口的语法。主要方便直接用Lambda表达式构造出实例,让代码更加简洁。
- 增加了default方法和static方法。default方法属于实例,声明对象后可调用;static方法属于类(接口),可以直接利用接口名调用。default方法为默认方法,有方法体,抽象类(abstract
Class)或类(Class)实现此接口时可以覆写default方法。static方法是隶属于此接口的静态方法,和平常的static方法没区别。
//A接口
//此接口为函数式接口,只能有一个抽象方法
//用于在编译期间检查接口是否符合函数式接口的语法
@FunctionalInterface
public interface FunctionInterA {
static String names = "张三";
//默认方法,有方法体
default String name(String name){
return "早上好"+name;
}
//静态方法,有方法体
static void close(){
System.out.println("此方法不可变"+names);
}
//普通接口
Integer age(int age);
}
- 接口中的静态方法不会被继承,接口中的静态变量(static
names=”张三”)会被继承。类或抽象类不能获得接口的static方法,只能通过FunctionInterA.close()获得,但是可以获得静态变量,即在类中可以访问names常量。 - 如果一个抽象类或类实现多个接口且接口中有名称相同的方法(无论是普通方法还是default方法),类必须通过override覆写所有接口中同名的方法。
//B接口
@FunctionalInterface
public interface FunctionInterB {
//默认方法,有方法体
default String name(String name){
return "中午好"+name;
}
Double money(double m);
}
在FunctionInterA和FunctionInterB中都有default方法name,让类实现这两个接口。
public class Test2 implements FunctionInterA,FunctionInterB{
@Override
public String name(String name){
return "晚上好"+name;
}
@Override
public Integer age(int age){
return 1+age;
};
@Override
public Double money(double m){
return 2.2+m;
}
public static void main(String[] args) {
FunctionInterA functionInterA = age -> 1+age; //A接口实例
FunctionInterB functionInterB = m -> 3.0+m; //B接口实例
Test2 test2 = new Test2(); //类的实例
System.out.println("A接口的默认方法为"+functionInterA.name("张三"));
System.out.println("B接口的默认方法为"+functionInterB.name("张三"));
System.out.println("类的name方法为"+test2.name(Test2.names));
}
}
输出结果为:
A接口的默认方法为早上好张三
B接口的默认方法为中午好张三
类的name方法为晚上好张三
2.四大函数接口
四个函数式接口(@FunctionalInterface)分别为:Consumer< T>(消费型)、Supplier< T>(供给型)、Function<T,R>(函数型)、Predicate< T>(断言型)。
1.Consumer
- Consumer< T>:消费型接口。接口方法 void accept(T
t):参数类型是T,无返回值。由于输入时有参数,输出无返回值,可以理解为把参数给消费了,成为消费型接口。消费型接口代表了在一个输入参数上需要进行的操作。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
实例:函数式接口相当于把一个行为当作参数传入一个方法中,在Consumer的accept方法中没有返回值,需要对传入的参数做一些变化或者对传入参数与其他变量发生联系,否则就没有意义。Consumer作为一个参数,可以在accept方法的前后添加代码dosomething,在调用方法时,只需要利用Lambda表达式或匿名内部类重写accept方法即可,其他函数接口类似。
public class Test4 {
public void encodePass(String str, Consumer<String> consumer){
String s = str + "你好";
consumer.accept(s);
}
public static void main(String[] args) {
Test4 test4 = new Test4();
String beforePass = "123561";
System.out.println("加密前密码为"+beforePass);
test4.encodePass(beforePass,(t)-> {
try{
System.out.println("机密后密码为"+DigestUtils.md5DigestAsHex(t.getBytes()));
}catch (Exception e){
e.printStackTrace();
}
});
}
}
也可以直接用Consumer<类型>进行接收(单纯的重写accept方法),代码如下:
public class Test5 {
public static void main(String[] args) {
String beforePass = "15641864";
System.out.println("加密前密码为"+beforePass);
Consumer<String> consumer = t->{
try{
System.out.println("加密后密码为"+ DigestUtils.md5DigestAsHex(t.getBytes()));
}catch (Exception e){
e.printStackTrace();
}
};
consumer.accept(beforePass);
}
}
2.Supplier
- Supplier< T>:供给型接口。接口方法 T
get():无参数,返回T类型参数。由于没有输入,凭空能产生输出,新增了东西,成为供给型接口。供给型接口提供一个给定参数类型的结果。
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
没有输入参数,产生一个随机值并输出:
public class Test6 {
public static void main(String[] args) {
Supplier<Double> integerSupplier = ()->Math.random();
System.out.println("产生的随机数为"+integerSupplier.get());
}
}
3.Function
- Function<T,R>:函数型接口。接口方法R
apply(T):对类型T参数操作,返回R类型参数。由于有输入参数T,也有输出值R,且输入和输出类型可以不同,类似于函数,称为函数接口。Function接口接收一个参数,并返回单一的结果。
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
对一个字符串进行加密并获得加密后的值:
public class Test7 {
public static void main(String[] args) {
String beforePass = "asdasd";
Function<String,String> function= (T)-> DigestUtils.md5DigestAsHex(T.getBytes());
System.out.println("加密后密码为"+function.apply(beforePass));
function.apply(beforePass)为加密后的值,和Consumer不同
}
}
4.Predicate
- Predicate< T>:断言型接口。接口方法 boolean test(T t):对类型T进行条件筛选操作,返回boolean。
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
...一些默认方法和静态方法...
}
获取字符串长度大于等于5的List集合,可以自定义test函数实现不同的功能。
public class Test8 {
public List<String> filter(List<String> strings,Predicate<String> predicate){
List<String> stringList = new ArrayList<>();
for (String s:strings){
if (predicate.test(s)){
stringList.add(s);
}
}
return stringList;
}
public static void main(String[] args) {
Test8 test8 = new Test8();
List<String> strings = Arrays.asList("aaaaa","sdd","sadasd","asdd","afasd");
List<String> list = test8.filter(strings,t->t.length()>=5);
System.out.println(list.toString());
}
}
本人小白一个,如果有什么问题还请您在评论区留言!感谢