1. 程式人生 > >java8介面預設方法和靜態方法

java8介面預設方法和靜態方法

java8中對介面進行了擴充套件,允許我們在介面中定義具體方法,一種是預設方法,即在方法返回值前加“default”關鍵字,另一種是加“static”的靜態方法。

擴充套件帶來的好處

1.java擁有了類似多繼承的功能,雖然在物件關係中,繼承關係和實現關係還是有有所區別,但是在作用上與C++的多繼承類似;

2.介面可以幫我們實現一些比較固定的方法,不必每次實現一個介面就得實現所有方法;

3.向前相容,如果要在介面中新增一個新的方法,在沒有預設方法前,修改了介面,那實現介面的類都得多實現一個可能對他們來說沒用的類,可擴充套件性不好,就好比java8新增的lambda表示式,預設方法就起到過渡作用。

@FunctionalInterface  
public interface Iterable<T> {  
    Iterator<T> iterator();  
   
    default void forEach(Consumer<? super T> action) {  
        Objects.requireNonNull(action);  
        for (T t : this) {  
            action.accept(t);  
        }  
    }  
}
Iterable介面在java8之後添加了一個預設方法forEach,forEach 使用了一個java.util.function.Consumer功能介面(函式式介面)型別的引數,它使得我們可以傳入一個lambda表示式或者一個方法引用,如下:
List<?> list = …
list.forEach(System.out::println);

衝突

現在來看看使用預設方法會遇到的一些衝突

1.一個類實現了介面A和B,A和B中都有一個方法簽名一樣的方法foo,這種情況下編譯不通過,因為編譯器無法判斷我們想要使用的是哪個foo(),這時候實現類就必須對foo方法進行重寫,在方法裡決定要呼叫的是A的還是B的foo(),或者都不呼叫,下面的例子我使用A.super.foo();呼叫A的foo()。

public class Jdk8DefaultMethod implements A, C {
    // 若此處重寫foo(),那麼呼叫的就是此類中的foo()了
}
interface A {
    default void foo() {
        System.out.println("default method of A");
    }
}
interface C extends A {
    // 重寫方法優先
    @Override
    default void foo() {
        System.out.println("default method of C");
    }
}
2.修改一下上面的程式碼,一個類實現了介面A和C,而介面C繼承了介面A並重寫了A介面的foo方法,這種情況下實現類在不重寫foo()的情況下會呼叫C介面中的foo(),重寫過的方法被JVM認為更具體,更重要,所以這種情況下是重寫方法優先。如果實現類也重寫了foo()一樣,那麼呼叫的就是實現類中的foo()了。
public class Jdk8DefaultMethod implements A, C {
    // 若此處重寫foo(),那麼呼叫的就是此類中的foo()了
}
interface A {
    default void foo() {
        System.out.println("default method of A");
    }
}
interface C extends A {
    // 重寫方法優先
    @Override
    default void foo() {
        System.out.println("default method of C");
    }
}
3.繼續修改,如果一個類實現了介面A和D,介面A中的foo()是預設方法,而介面D中的foo()是抽象方法,這種情況下,實現類必須重寫介面D中的foo(),呼叫的也是介面D的foo()。
public class Jdk8DefaultMethod implements A, D {
    // 重寫介面D中的foo()
    @Override
    public void foo() {
        System.out.println("Override foo of interface D");
    }
}
interface A {
    default void foo() {
        System.out.println("default method of A");
    }
}
interface D {
    // 對介面定義的抽象方法的實現方法優先呼叫
    void foo();
}

預設方法的簡單使用

繼續修改上面的類,利用介面的預設方法創造一個模板方法,其中getSession()和close()方法是介面幫我們實現好的,我們只需要重寫邏輯不固定的service()。
/**
 * writer: holien 
 * Time: 2017-11-26 14:46 
 * Intent: 預設方法以及多繼承衝突 
 */  
public class Jdk8DefaultMethod implements MyTemplate {  
    @Override  
    public void service() {  
        System.out.println("使用者自己實現的業務邏輯");  
    }  
  
    public static void main(String[] args) {  
        Jdk8DefaultMethod object = new Jdk8DefaultMethod();  
        object.doTemplate();  
    }  
}  
interface MyTemplate {  
    void service();  // 根據不同需求重寫此方法  
    default void doTemplate() {  
        getSession();  
        service();  
        close();  
    }  
    // 邏輯不變的兩個方法,使用預設方法封裝實現  
    default void getSession() {  
        System.out.println("自動獲取會話");  
    }  
    default void close() {  
        System.out.println("關閉連線");  
    }  
}
以上是對預設方法的理解和使用,對於介面中的靜態方法,暫時還不瞭解有什麼具體用法和實踐,以後會補上。

java8之後的介面和抽象類的區別

介面的變數預設是public static final 型,且必須給其初始值,抽象類的變數預設是default的,可重新賦值;

在語法上,一個類的抽象類只能有一個,但是可以擁有多個介面。

相關推薦

java8介面預設方法靜態方法

java8中對介面進行了擴充套件,允許我們在介面中定義具體方法,一種是預設方法,即在方法返回值前加“default”關鍵字,另一種是加“static”的靜態方法。 擴充套件帶來的好處 1.java擁有了類似多繼承的功能,雖然在物件關係中,繼承關係和實現關係還是有有所區別,但

Java8新特性之介面預設方法靜態方法

我們都知道應該面向介面程式設計。介面給定使用者應該使用的協議,而不用依賴該介面的具體實現細節。 因此,為了做到鬆耦合,設計出乾淨的介面成為API設計的要素之一。SOLID五大原則之一的要求我們設計有具體目的的小介面,而不是一個通用卻臃腫的介面。對你的類庫和

java8新特性二:介面預設方法靜態方法

java8中允許在介面中有普通方法。方法要用default修飾比如 default String getpassword (St

Java8新特性】介面中的預設方法靜態方法,你都掌握了嗎?

## 寫在前面 > 在Java8之前的版本中,介面中只能宣告常量和抽象方法,介面的實現類中必須實現介面中所有的抽象方法。而在Java8中,介面中可以宣告預設方法和靜態方法,本文,我們就一起探討下介面中的預設方法和靜態方法。 ## 介面中的預設方法 Java 8中允許介面中包含具有具體實現的方法,該

Java 8-介面預設方法靜態方法

Java 8-介面的預設方法和靜態方法   Java 8使用兩個新概念擴充套件了介面的含義:預設方法和靜態方法。預設方法使得介面有點類似traits,不過要實現的目標不一樣。預設方法使得開發者可以在 不破壞二進位制相容性的前提下,往現存介面中新增新的方法,即不強制那些實現了該介面的類也

JDK8新特性 介面的變化--預設方法靜態方法

本文主要是簡單的說明下jdk8出現的一個新特性–介面的增強。此次變化中,介面中某些方法也可以有方法體了。jdk8對於介面的設計,除了保留之前的版本記本特性外,還提供了兩個新的功能。除了抽象方法外,還可以有預設方法(default方法)和靜態方法(static方法

php 普通方法靜態方法

普通 ntc 靜態 urn ade ati 標識符 count() student <?php header(‘Content-Type: text/html; charset=utf-8‘); class Student { public static funct

jdk1.8新特性 : 接口中可以有普通方法(非靜態方法)靜態方法 , 顛覆了之前我的理解 : 接口中只能有共有常量抽象方法的概念,後面必須要加一句jdk1.71..7之前

@override 編譯 sys 接口 blank new style nts highlight 看到jdk某些接口中存在default方法,於是... http://shaomeng95.iteye.com/blog/998820 為什麽接口只能是公有常量? p

一文詳解python的類方法,普通方法靜態方法

http 接下來 方法調用 pytho 類和實例 訪問類 靜態 都是 com   首先形式上的區別,實例方法隱含的參數為類實例self,而類方法隱含的參數為類本身cls。 靜態方法無隱含參數,主要為了類實例也可以直接調用靜態方法。   所以邏輯上,類方法被類調用,實例方法

synchronized修飾普通方法靜態方法

對象 -s 修飾 style 安全 安全問題 才會 htable 會有 首先,要知道,synchronized關鍵字修飾普通方法時,獲得的鎖是對象鎖,也就是this。而修飾靜態方法時,鎖是類鎖,也就是類名.class。 synchronized修飾普通方法 Synchron

C# 動態方法靜態方法的區別

內存 法則 靜態 操作類 ret 我們 數據庫操作類 body method C# 動態方法和靜態方法的區別 (轉) 動態方法與靜態方法的區別: 1,使用方法上的區別:動態方法,在使用時需要先創建實例,才能調用實例方法,而靜態方法則不需要,直接使用即可。 示例代碼如下

20180727 (面向對象的屬性 類方法靜態方法)

python 復用性 減少 整體 調用 參數 空間 遇到 @property 一.屬性:將一個方法,偽裝成一個屬性,在代碼的級別上沒有本質的提升,但是可以讓其看起來更合理 property:類似於bmi這種,看起來像名詞,實際是需要計算的(動詞),或者遇到周長或者面積這種詞

Java 8——接口中個的默認方法靜態方法

string 深入 col 函數 cti code 引用 lan mov 在Java SE 8之前,interface只是事物的抽象,用來定義統一的抽象事物和描述事物的抽象行為和屬性。 但是在Java SE 8中,增加了可以在interface中增加默認實現的行為和事物的靜

python之property、類方法靜態方法

new 增刪改查 turn 引用 dict 沒有 不同的 保護 實例化 一、完整的property1、定義一個方法被偽裝成屬性之後,應該可以執行一個屬性的增刪改查操作,增加和修改就對應著被setter裝飾的方法,刪除一個屬性對應著被deleter裝飾的方法。 @prope

JDK8.0接口中的默認方法靜態方法

div inter pri 默認方法 over main 值類型 Speak 普通 我們在接口中通常定義的方法是抽象方法,即沒有方法體,只有返回值類型和方法名:(public abstract) void Method(); 類在實現接口的時候必須重寫抽象方法才可以 jdk

Python中的類方法靜態方法

作者:黎智煊 ,叩丁狼高階講師。本文為原創文章,轉載請註明出處。     類方法 是類物件所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個引數必須是類物件,一般以cls作為第一個引數(當然可以用其他名稱的變數作

Python的例項方法、類方法靜態方法之間的區別與聯絡

Python的例項方法、類方法和靜態方法 class Test: def test1(self): print('test......') @classmethod def test2(cls): print('test2......c

python:類方法靜態方法

1.類方法: 類屬性就是針對類物件定義的屬性                    使用賦值語句在class關鍵字下方可以定義類屬性      

python筆記(封裝(含類方法靜態方法))

一、封裝: 1、廣義上面向物件的封裝:程式碼的保護,面向物件的思想本身就是一種封裝 2、只讓自己的物件能呼叫自己類的方法 3、狹義上的封裝 – 面向物件三大特性 4、屬性和方法都藏起來,不讓你看見 class Person: def __init__(self,name,pass

Python學習手冊之數據封裝、類方法靜態方法

tle tro 變量 無法 code att span method 私有 在上一篇文章中,我們介紹了 Python 的內部方法、操作符重載和對象生命周期,現在我們介紹 Python 的數據封裝、類方法和靜態方法。查看上一篇文章請點擊:https://www.cnblogs