java8新特性之函式式介面
雖然剛釋出了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);
}