主頁 > 後端開發 > Java面對物件-介面【介面的使用、介面和抽象類區別、介面的默認方法、匿名內部類和介面抽象類】

Java面對物件-介面【介面的使用、介面和抽象類區別、介面的默認方法、匿名內部類和介面抽象類】

2021-12-20 07:31:03 後端開發

介面的概念:

官方解釋:Java介面是一系列方法的宣告,是一些方法特征的集合,一個介面只有方法的特征沒有方法的實作,因此這些方法可以在不同的地方被不同的類實作,而這些實作可以具有不同的行為(功能,即子類可以重寫抽象類的方法),
在介面中,它的方法是絕對抽象的(jdk8以前),用來抽象子類的能力、規則,例如鳥的fly,🐟的swim,數字能夠Compare,這就是鳥類,🐟類的能力,

在現實中也有很多事物用到了介面的概念
例如:資料線,在使用資料線充電時,只要你使用安卓的資料線,一般都能夠給安卓手機充電,因為這類充電線的插口都按照Android的規則、規格來生產資料線,這里使用到的是介面能定義規則(資料線并不是真正使用了JAVA中的介面,而是資料線的插口被制定了一個生產規則,包括插口大小,內部接線規則,假如我們要寫一個資料線的類,那么我們可以將這些規則以常量或者無方法體的抽象方法寫入介面中)
生活中很多物品的規格都是嚴格要求好的,這有利于產品的拓展,
對于面對物件的java語言也是如此,物件是用來描述、描繪一個事物的,有了介面,可以提高物件的擴展性,靈活性,


介面中除了默認方法和靜態方法,都沒有方法體

  1. 在jdk8以前,所有方法都是抽象的.
  2. 介面沒有方法體,是因為,介面是用來規范代碼,使得代碼結構更清晰,
  3. jdk8,介面可以有默認方法,默認方法有方法體,并且子類可以不實作默認方法,直接使用,也可以覆寫介面的方法
    意義:現在有一個介面和若干個實作該介面的類,假如只是部分介面需要這個新方法,那怎么辦?
    1.在介面中直接添加新方法:所有類都要實作該方法,很麻煩
    2.使用抽象類(建議看完下面抽象類再來看這個):使用抽象類實作介面并添加新方法,需要實作的子類繼承自抽象類即可
    3.在介面中添加默認方法!!
  4. 介面無法實體化


一個類可以實作多個介面


介面可以繼承其他介面,并且可以多繼承介面,但是介面介面需要使用extends

public interface InterfaceB extends InterfaceA,InterfaceC{
}
//這里要注意了,介面繼承介面,介面可以不實作其父介面的抽象方法
//雖然這個介面里面沒有抽象方法,但是實作這個介面的類必須實作介面A中的方法
//即:類實作某個介面,從層級關系上講,類必須實作其介面層級往上的所有的抽象方法
public interface InterfaceA {
	void doWork();
}
public interface InterfaceC {
}


一個類如果要實作某個介面,需要實作其中所有的抽象方法
1.因為介面是提取規則、能力,實作這個介面肯定就有這種能力,既然介面都抽象了這種方法,那子類都應該有這些方法,


為什么需要介面?

  1. java無法多繼承,介面可以用來抽象特性,可以彌補無法多繼承的局限,同時也避免了多繼承的復雜性
  2. 良好的代碼書寫規范和清晰的代碼層級關系利于原始碼的閱讀和理解

介面無法實體化


介面的方法都是public的

  1. 因為介面是提取規則,沒有子類實作介面,介面就沒存在的意義了,要被子類實作,public是最好的,不同包內也可以實作這個介面

介面中的屬性默認public static final

  1. 因為介面中抽象的是規則,規則不應該能被改變,并且能被子類使用,定義靜態常量時候必須有初始值

介面也有標識作用:

  1. 例如Serializable,其內部是連抽象方法都沒有的,沒有內容,這個介面的作用只是標識這個類具有某種功能,
    在這里插入圖片描述



抽象類的概念:
面對物件中,物件都是通過類來描述的,有很多相似的物件,這些類中有很多相似的內容,抽象類提取這些類的共性內容后,作為子類的模板,
1. 抽象類中必須含有抽象方法,可以有普通方法
2. 可以有變數、常量
3. 子類只能單繼承,即子類繼承了某抽象類無法繼承其他類
4.抽象類不能實體化,抽象類用來就是提取子類模板,是用來被繼承的,
但是可以以匿名內部類的形式來創建一個物件

  •   public static void main(String[] args) {
          Animals sheep=new Animals() {
              @Override
              public void eat(String food) {
                  System.out.println("羊吃"+food);
              }
          };
          sheep.eat("草");
          Animals fish=new Animals() {
              @Override
              public void eat(String food) {
                  System.out.println("魚吃"+food);
              }
          };
          fish.eat("水草");
      }
    

}
這里就是兩個匿名抽象類物件,這里$就代表是匿名物件,在這里插入圖片描述匿名內部類?為什么匿名內部類有參考?以及介面怎么實作匿名方式?

public class Anonymous {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.tiger.cry();
        outer.dog();
    }
}
interface IA{
    void cry();
}

class Outer{
    //如果要使用IA介面,并創建物件,傳統方式是寫一個類實作介面并創建物件
    //但是這個類只需要使用一次所以使用匿名內部類來簡化開發
    //匿名內部類的名字由系統自動分配,需要使用物件.getclass
    //介面其實是無法new的,但是這里通過大括號并實作其中的方法,是的其可以創建并且將地址傳遞給tiger
    //匿名內部類只能使用一次,但是已經創建的tiger可以多次使用
    //這里其實是實作IA介面的內部類
    IA tiger=new IA() {
        @Override
        public void cry() {
            System.out.println("老虎狂嘯");
        }
    };

    public void dog() {
        IA dog = new IA() {
            @Override
            public void cry() {
                System.out.println("小狗汪汪");
            }
        };
    }
    new Father(){
      @Override
      publi void ih(){
        sop("匿名內部類呼叫了hi方法")
      }
    }.hi();//這樣甚至都不用創建變數,直接呼叫
    //體現了匿名內部類的物件的特征
    
    Father father=new Father("jack"){
        //匿名內部類中不能重寫構造器,不能創建特有方法
        //運行型別是Outer$3
        //這里可以重寫father的方法
        //這里相當于繼承了一個類,省去了創建不必要的新的子類
        @Override
        public void test() {
            super.test();
        }
    };//這里有大括號,所有是匿名內部類
//    Father father=new Father("jack");這里是直接創建father物件
}


class Father{
    String name;
    public Father(String name){
        this.name=name;
    }
    public void test(){
        System.out.println("name="+name);
    }
}

介面和抽象類的區別

但是我先舉一個實際的例子,來解釋介面的作用,在此同時也會介紹抽象類和介面的區別


這里我們先假設我們需要實作一種抽象的數字類,來思考一下其需要實作什么功能

  1. 能保存用戶傳給的值
  2. 能和其他數字比較(數字不能比較還有什么意義)
  3. 可以來輸出保存的值
  4. 最大能保存數字的范圍
  5. 能和其他數字進行轉換

先別急,現在我們來看一下Java中是如何實作數字類及其子類的
這個是IDEA中的Digrams,想使用可以IDEA中Digrams的使用
在這里插入圖片描述來看一下源代碼

public abstract class Number implements java.io.Serializable {
    public abstract int intValue();//對應上方的保存值功能,注意這里的所有方法都沒有方法體
    public abstract long longValue();//回傳值(相當于保存值、輸出值)
    public abstract float floatValue();//同上
    public abstract double doubleValue();
    public byte byteValue() {//強制轉換
        return (byte)intValue();
    }
    public short shortValue() {
        return (short)intValue();
    }
    private static final long serialVersionUID = -8742448824652078965L;
}

再看一下實作Number抽象類的Integer的原始碼

public final class Integer extends Number implements Comparable<Integer>{//注意這里繼承了Number抽象類和Comparable介面
	//保存值的范圍
    @Native public static final int   MIN_VALUE = 0x80000000;
    @Native public static final int   MAX_VALUE = 0x7fffffff;
   
    //輸出值
    public static String toString(int i, int radix){
    ....省略
    }
    //保存值
    public int intValue() {
        return value;
    }
    static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
    ....省略
    }
    //和其他Integer類比較
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    //轉換成其他數字類
    public long longValue() {
        return (long)value;
    }
   
}

再來看一下Comparable介面

public interface Comparable<T> {
    public int compareTo(T o);
}
//comparable介面中引數使用了泛型,不同的類實作不同的comparable介面即可,實作comparable介面的類需要實作其中的compareTo方法

現在我們思考幾個問題(以下問題均是個人的想法,若不全,若有錯誤可聯系我補充或者更改答案)

  1. 為什么Comparable是一個介面
    解:在撰寫代碼的時候,我們要使得代碼結構清晰,需要規范代碼,這也是抽象類,父類,介面存在的意義之一.使用介面可以提取類的規則,抽象類可以提取類的共性內容,對于比較功能,數字肯定是可以比較是吧,但是很多其他類,比如自己創建一個employee和employer類,兩個類之間可以有工資的比較方法或者其他比較方法,所以說Comparable應該是一個規則,Comparable作為介面最好,這樣有比較功能的類實作該介面就行,如果,有比較功能的類的不實作comparable介面,卻私自定義一個compare方法,那么介面存在的意義就被忽略了,
    其次,Java無法實作多繼承,這意味著假如Comparable是抽象類的話,那我們又如何讓Integer繼承Number類,兩個類無法同時被一個類繼承,這里也側面體現了,介面可以解決java無法多繼承的局限,
  2. 為什么Number是一個抽象類
    解:抽象類抽取的是子類的特性、共性內容,可以看見Number類中有一些回傳數值和保存數值的方法以及轉換方法,這很明顯是所有數字類的共性內容,先前介紹了數字類應該有的五個個功能,回傳和保存以及轉換只是其中三個功能,但是
    為什么數字范圍沒在抽象類中:上面Integer保存范圍是用的final常量,抽象類雖然可以有final屬性,但是不同數字類保存范圍不一樣,不是共同內容
    為什么Number中沒有實作Comparable介面,而是其子類去實作Comparable介面:因為Comparable介面有泛型引數T,實作該介面的時候需要填寫引數,所以放在抽象類Number的子類中最合適,方便實作Comparable的CompareTo方法,


    我這里寫了一個小代碼
public class IntegetTest extends NumberTest{
    @Override
    public int compare(NumberTest numberTest) {
        return 0;
    }
    @Override
    public int compareTo(NumberTest o) {
        return 0;
    }
}

假如有數字類繼承了這個介面,其子類需要實作這個compare方法以及compareTo方法并且引數是NumberTest抽象類,


我們看看Double繼承了Number抽象類,那Double怎么實作compareTo方法的

	  ......上方其他代碼省略
    public int compareTo(Double anotherDouble) {
        return Double.compare(value, anotherDouble.value);
			//value是newDouble類是保存在Double類中的一個值,體現了Double保存數值的功能
    }
    public static int compare(double d1, double d2) {
        if (d1 < d2)
            return -1;           // Neither val is NaN, thisVal is smaller
        if (d1 > d2)
            return 1;            // Neither val is NaN, thisVal is larger

        // Cannot use doubleToRawLongBits because of possibility of NaNs.
        long thisBits    = Double.doubleToLongBits(d1);
        long anotherBits = Double.doubleToLongBits(d2);

        return (thisBits == anotherBits ?  0 : // Values are equal
                (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
                 1));                          // (0.0, -0.0) or (NaN, !NaN)
    }
    ....下方其他代碼省略

不需要理解很多,這里的compareTo方法使用了Double中保存的value,我們思考一下,假如是Number實作comparable介面,那么子類方法引數應該就是抽象類了,但是抽象類中雖然有保存數值的方法,但是并沒有方法體,如果Number實作該介面,其子類的CompareTo方法和Compare方法的實作會變得麻煩很多,(希望有人能提出關于這部分更好的意見!!)

  1. 為什么Number不能設計成一個介面
    Number是一種模板,它偏向于提取子類的共性內容,介面偏向于提取規則,所以寫成抽象類比較方便

案例總結:

  1. 抽象類偏向于提取子類共有內容,介面偏向于提取規則,
  2. 抽象類是一種子類模板
  3. 合理的介面、抽象類使用可以讓代碼的關系更加清晰,事實上,介面可以提供多繼承的大多數好處,同時還能避免多繼承的復雜性,
    如何查看自己所寫的類的關系 ,可以使用Idea的Digrams功能
    Idea中超贊的的Digrams功能

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/386571.html

標籤:java

上一篇:Java 常用資料型別的輸入輸出

下一篇:XML實驗報告(XML,DTD,SCHEMA,XPATH,XSLT,利用JAVA對XML進行讀寫操作)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more