虽然刚发布了java11版本,但是对于java8中新的特性我们仍需要掌握,毕竟大部分开发都是用的jdk8,以及java11中仍然保留着这些特性,接下来我就网上查找资料做了一下总结,如果哪里说的不对头,还请各位大佬指出来,我会及时更正。
1.函数式接口定义:
那么函数接口到底是什么呢?是个接口,只包含一个抽象方法,则该接口称之为函数式接口,我们可以在任意函数式接口上使用 @FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解,如:
public interface Test { default void defaultMethod(){ System.out.println("Test defalut 方法"); } int sub(int a,int b); static void staticMethod() { System.out.println("Test static 方法"); } }
2.特点
函数式接口里是可以包含默认方法、静态方法,他们不是抽象方法;也可以包含Java.lang.Object里的public方法,因为任何一个类都继承Object类,包含了来自java.lang.Object里对这些抽象方法的实现,也不属于抽象方法;函数式接口里允许子接口继承多个父接口,但每个父接口中都只能存在一个抽象方法,且必须的相同的抽象方法,一般和Lamdba表达式一起用,总结下分为两点:
①函数式接口是仅制定一个抽象方法的接口,
②可以包含一个或多个静态或默认方法.
3.该类接口中的static方法不能被继承,也不能被实现类调用,只能被自身调用
定义一个函数式接口:
public interface DefalutTest { static int a =5; default void defaultMethod(){ System.out.println("DefalutTest defalut 方法"); } int sub(int a,int b); static void staticMethod() { System.out.println("DefalutTest static 方法"); } }
实现该接口:
public class DefaultTestImpl implements DefalutTest{ @Override public int sub(int a, int b) { // TODO Auto-generated method stub return a-b; } }
测试:
public static void main(String[] args) { DefaultTestImpl dt = new DefaultTestImpl(); dt.defaultMethod(); //接口中的默认方法可以通过实现类对象调用 DefalutTest.staticMethod();//接口中静态不能通过实现类对象调用,只能通过接口本身调用 }
发现实现类对象能够调用接口的默认方法,不能调用静态方法。但是静态方法可通过接口本身调用。
继承也是这种情况,就不细说了。所以得出结论:
接口里的静态方法,即static修饰的有方法体的方法不会被继承或者实现,但是静态变量会被继承
4.该类接口中的默认方法
①default方法可以被子接口继承亦可被其实现类所调用
准备一个子接口继承DefalutTest接口
public interface SubTest extends DefalutTest{ }
准备一个子接口的实现类
public class SubTestImp implements SubTest{ @Override public int sub(int a, int b) { // TODO Auto-generated method stub return a-b; } }
现在我们创建一个子接口实现类对象,并调用对象中的default方法:
public class Main { public static void main(String[] args) { SubTestImp st = new SubTestImp(); stl.defaultMethod(); } }
执行结果:
DefalutTest defalut 方法
②default方法被继承时,可以被子接口覆写
现在我们在子接口中重写default方法,在进行调用:
public interface SubTest extends DefalutTest{ default void defaultMethod(){ System.out.println("SubTest defalut 方法"); } }
执行结果:SubTest defalut 方法
③如果一个类实现了多个接口,且这些接口中无继承关系,这些接口中若有相同的(同名,同参数)的default方法,则接口实现类会报错,接口实现类必须通过特殊语法指定该实现类要实现那个接口的default方法
我们去除接口间的继承关系,并使得SubTestImp同时实现父接口和子接口,我们知道此时父接口和子接口中存在同名同参数的default方法,这会怎么样?
结果实现类报错,实现类要求必须指定他要实现那个接口中的default方法:
解决方法:使用特殊语法:<接口>.super.<方法名>([参数])
public class SubTestImp implements SubTest,DefalutTest{ @Override public int sub(int a, int b) { // TODO Auto-generated method stub return a-b; } @Override public void defaultMethod() { // TODO Auto-generated method stub DefalutTest.super.defaultMethod(); } }
5.Java8内置函数式接口
四大核心函数式接口
函数式接口 | 方法 | 参数类型 | 返回类型 | 作用 |
---|---|---|---|---|
Consumer<T> 消费型接口 | void accept(T t) | T | void | 对T类型的参数进行操作 |
Supplier<T> 供给型接口 | T get() | 无 | T | 操作数据,返回T类型的结果 |
Function<T, R> 函数型接口 | R apply(T t) | T | R | 对T类型参数进行操作,并返回R类型的结果 |
Predicate<T> 断定型接口 | boolean test(T t) | T | boolean | 确定T类型参数是否满足某约束,并返回boolean值 |
//Consumer<T> 消费型接口 @Test public void test1(){ Consumer<String> c = (x) -> System.out.println("hello:"+x+"!"); c.accept("Java"); } // Supplier<T> 供给型接口 @Test public void test2(){ Supplier<String> s = () -> "hello,beautiful girl"; String str = s.get(); System.out.println(str); } //Function<T,R> 函数性接口 @Test public void test3(){ Function<String, Integer> f= (x) -> x.length(); Integer len = f.apply("hello"); System.out.println(len); } //Predicate<T> 断言型接口 @Test public void test4(){ Predicate<String> p = (x) -> x.length()>5; boolean b = p.test("hello Java"); System.out.println(b); }