虽然刚发布了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 |
void accept(T t) | T | void | 对T类型的参数进行操作 |
Supplier |
T get() | 无 | T | 操作数据,返回T类型的结果 |
Function |
R apply(T t) | T | R | 对T类型参数进行操作,并返回R类型的结果 |
Predicate |
boolean test(T t) | T | boolean | 确定T类型参数是否满足某约束,并返回boolean值 |
//Consumer 消费型接口
@Test
public void test1(){
Consumer c = (x) -> System.out.println("hello:"+x+"!");
c.accept("Java");
}
// Supplier 供给型接口
@Test
public void test2(){
Supplier s = () -> "hello,beautiful girl";
String str = s.get();
System.out.println(str);
}
//Function 函数性接口
@Test
public void test3(){
Function f= (x) -> x.length();
Integer len = f.apply("hello");
System.out.println(len);
}
//Predicate 断言型接口
@Test
public void test4(){
Predicate p = (x) -> x.length()>5;
boolean b = p.test("hello Java");
System.out.println(b);
}