BD1 - Java 2-1 抽象類 接口 內部類

We believe that writing is about content, about what you want to say – not about fancy formatting.
我們堅信寫作寫的是內容蜕猫,所思所想绑警,而不是花樣格式。
— Ulysses

Java第5天上午

上午主要講了抽象類和接口

抽象類:

問題提出:


1

利用多態(tài)性實現(xiàn)不合理:


利用多態(tài)性實現(xiàn)不合理

抽象的概念定義為抽象類/抽象方法更加合理
注意上圖中抽象方法的形式 沒有{ }!

抽象類的特點:

抽象類的特點

  • 抽象類不能直接實例化岂却,但可以聲明出對象的引用以指向非抽象子類的對象(格式統(tǒng)一 方便編程)
  • 除非子類采用具體方法替代抽象類中的全部抽象方法,否則子類本身也被自動認為是抽象的泽西!此時必須手動在子類上加上abstract關鍵字7鹑摇7毂颉萌焰!

編程練習:編寫程序,創(chuàng)建兩個幾何對象谷浅,一個圓和一個正方形扒俯,調用方法檢查兩個對象是否有相同的面積,

// Shape.java:
public abstract class Shape {
    /**
     * 抽象獲取面積的方法 
     * @return 形狀面積
     */
    public abstract double getArea();
    /**
     * 比較兩個形狀的大小
     * @param p 另一個形狀的實例
     * @return 如果當前形狀較大則返回true
     */
    public boolean compareArea(Shape p){
        return this.getArea()>p.getArea();
    }
}

// Circle.java: 
public class Circle extends Shape{
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double getArea() {
        return Math.PI*radius*radius;
    }
}

// Square.java:
public class Square extends Shape{
    private double length;
    public Square(double length) {
        this.length = length;
    }
    @Override
    public double getArea() {
        return length*length;
    }
}

// Test.java:
public class Test {
    public static void main(String[] args) {
        Shape s1 = new Square(2);
        Shape s2 = new Circle(2);       
        System.out.println(s1.getArea());
        System.out.println(s2.getArea());
        System.out.println(s1.compareArea(s2));
    }
}

// 結果:
4.0
12.566370614359172
false

接口:

接口更抽象壳贪,僅聲明了方法:


接口僅聲明了方法
  • 注意接口用 interface 關鍵字

implements關鍵字實現(xiàn)接口:

implements實現(xiàn)接口

  • 通過這樣的定義陵珍,Professor類替代了Teacher接口的所有方法,因此Professor類是一個具體的類违施。
  • 但是如果Professor類沒有替換所有的接口互纯,則Professor類只能看成是一個抽象的類。編譯器會要求在Professor類的前面加上abstract關鍵字磕蒲。
  • 因此留潦,實現(xiàn)接口實際上就是在創(chuàng)建抽象類的子類時,給抽象方法“加上具體的內容”辣往。
Paste_Image.png

接口和抽象類區(qū)別:

接口與類
接口和抽象類
接口和抽象類
接口和抽象類2
接口和抽象類3
  • 接口與抽象類的不同:
    • 接口只抽象行為兔院,而抽象類則要指定屬性、具體的方法和抽象的方法站削。
    • 工程中坊萝,接口用的比抽象類更多一些
    • 抽象類只能單繼承,而接口可以多實現(xiàn)许起!但是十偶,當將繼承(或實現(xiàn))的子類有默認方法實現(xiàn)時,必須用抽象類(畢竟是個class园细,功能多一些)
接口和抽象類區(qū)別
接口和抽象類區(qū)別
Abstract class Interface
實例化 不能 不能
一種繼承關系惦积,一個類只能使用一次繼承關系∶推担可以通過繼承多個接口實現(xiàn)多重繼承 一個類可以實現(xiàn)多個interface
數(shù)據(jù)成員 可有自己的 靜態(tài)的不能被修改即必須是static final狮崩,一般不在此定義
方法 可以私有的蛛勉,非abstract方法,必須實現(xiàn) 不可有私有的睦柴,默認是public诽凌,abstract 類型
變量 可有私有的,默認是friendly 型坦敌,其值可以在子類中重新定義皿淋,也可以重新賦值 不可有私有的,默認是public static final 型恬试,且必須給其初值,實現(xiàn)類中不能重新定義疯暑,不能改變其值训柴。
設計理念 表示的是“is-a”關系 表示的是“l(fā)ike-a”關系
實現(xiàn) 需要繼承,要用extends 要用implements

一個類可以實現(xiàn)自多個接口:

類可以實現(xiàn)多個接口

類需要替代這兩個接口所定義的所有方法

重點說明: (用接口實現(xiàn)多重繼承)

Java不支持多重繼承原因

Java不支持多重繼承原因
  • 多重繼承發(fā)生問題原因之一在于屬性(數(shù)據(jù)結構)沖突妇拯,也就是存儲空間的沖突幻馁。由于接口不與任何存儲空間相關聯(lián),因此可以解決存儲空間沖突的問題

  • 對于繼承的方法的沖突越锈,當使用接口之后仗嗦,由于接口只定義了方法的抽象,沒有具體的執(zhí)行代碼甘凭,因此也不會發(fā)生代碼沖突的問題稀拐。

拓展示例:


示例
總結
  • 非抽象類(具體類)不能包含抽象方法
  • 如果抽象父類的子類,沒有實現(xiàn)所有的抽象方法丹弱,它必須聲明為抽象的(在這個類聲明的前面加上abstract關鍵詞) (貌似和前面重復了德撬,但是很重要,再說一次也無妨)
  • 在一個由抽象類擴展出來的非抽象類中躲胳,所有的抽象方法都必須實現(xiàn)蜓洪,即使這個子類不使用它們。
  • 抽象類不能用new運算符實例化坯苹,但仍應定義它的構造方法隆檀,這種構造方法將在它子類的構造方法中被調用。
  • 允許聲明沒有抽象方法的抽象類粹湃。(用于定義新子類)
  • 子類可以被聲明是抽象的恐仑,即使它的父類是具體的。
  • 子類可以覆蓋它父類的方法再芋,并將其聲明為抽象的菊霜。(當父類方法中的實現(xiàn)在子類中無效時)
抽象類可以用作數(shù)據(jù)類型

對比補充:


普通方法和抽象方法
普通類和抽象類
抽象類的優(yōu)勢

抽象類——模板設計模式:


模板設計模式

抽象類小練習:


練習
理解接口
  • 抽象類不能實例化,有構造方法济赎;接口也不能實例化鉴逞,但沒有構造方法记某!
實現(xiàn)多接口
  • 接口不是類,不能繼承類构捡,可以繼承一個或多個接口
  • 接口不能實現(xiàn)接口R耗稀!(只有類可以實現(xiàn)接口勾徽,注意區(qū)分實現(xiàn)和繼承接口的區(qū)別;埂)
  • 抽象類是類,既可以繼承類喘帚,也可以實現(xiàn)很多其他接口

final:

final

老師上午給的2個PPT請點我查看下載

拓展閱讀:

1 - Java 接口的作用和好處
2 - Java 接口(interface)的用途和好處
3 - Java 抽象類與接口的區(qū)別
4 - 詳細解析Java中抽象類和接口的區(qū)別

拓展:

了解Math類:
The class contains methods for performing basic numeric operations such as the elementary exponential, logarithm, square root, and trigonometric functions

里面包含了很多常用常量(如e和PI)和數(shù)學函數(shù)(如sin()畅姊、con()等):


Math.class

下午講了內部類:

Java內部類

在Java中,可以將一個類定義在另一個類里面或者一個方法(類成員函數(shù))里面吹由,這樣的類稱為內部類若未。廣泛意義上的內部類一般來說包括四種:

  • 成員內部類
  • 局部內部類
  • 匿名內部類
  • 靜態(tài)內部類

成員內部類:

  • 最普通的內部類,它的定義位于另一個類的內部
class Circle {
    double radius = 0;
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     // 成員內部類
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

看起來倾鲫,類Draw像是類Circle的一個成員粗合,Circle稱為外部類。成員內部類可以無條件訪問外部類的所有成員屬性和成員方法(包括private成員和靜態(tài)成員)

class Circle {
    private double radius = 0;
    public static int count =1;
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //內部類
        public void drawSahpe() {
            System.out.println(radius);  //外部類的private成員
            System.out.println(count);   //外部類的靜態(tài)成員
        }
    }
}

要注意的是乌昔,當成員內部類擁有和外部類同名的成員變量或者方法時隙疚,會發(fā)生隱藏現(xiàn)象,即默認情況下訪問的是成員內部類的成員磕道。如果要訪問外部類的同名成員供屉,需要以下面的形式進行訪問:

外部類.this.成員變量
外部類.this.成員方法

成員內部類可以無條件地訪問外部類的成員,而外部類想訪問成員內部類的成員卻不是這么隨心所欲了溺蕉。在外部類中如果要訪問成員內部類的成員贯卦,必須先創(chuàng)建一個成員內部類的對象,再通過指向這個對象的引用來訪問:

class Circle {
    private double radius = 0;
 
    public Circle(double radius) {
        this.radius = radius;
        getDrawInstance().drawSahpe();   //必須先創(chuàng)建成員內部類的對象焙贷,再進行訪問
    }
     
    private Draw getDrawInstance() {
        return new Draw();
    }
     
    class Draw {     //內部類
        public void drawSahpe() {
            System.out.println(radius);  //外部類的private成員
        }
    }
}

成員內部類是依附外部類而存在的撵割,也就是說,如果要創(chuàng)建成員內部類的對象辙芍,前提是必須存在一個外部類的對象啡彬。創(chuàng)建成員內部類對象的一般方式如下:

public class Test {
    public static void main(String[] args)  {
        //第一種方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必須通過Outter對象來創(chuàng)建
         
        //第二種方式:
        Outter.Inner inner1 = outter.getInnerInstance();
    }
}
 
class Outter {
    private Inner inner = null;
    public Outter() {
         
    }
     
    public Inner getInnerInstance() {
        if(inner == null)
            inner = new Inner();
        return inner;
    }
      
    class Inner {
        public Inner() {
             
        }
    }
}

內部類可以擁有private訪問權限、protected訪問權限故硅、public訪問權限及包訪問權限庶灿。比如上面的例子,如果成員內部類Inner用private修飾吃衅,則只能在外部類的內部訪問往踢,如果用public修飾,則任何地方都能訪問徘层;如果用protected修飾峻呕,則只能在同一個包下或者繼承外部類的情況下訪問利职;如果是默認訪問權限,則只能在同一個包下訪問瘦癌。這一點和外部類有一點不一樣猪贪,外部類只能被public和包訪問兩種權限修飾。

局部內部類:
局部內部類是定義在一個方法或者一個作用域里面的類讯私,它和成員內部類的區(qū)別在于局部內部類的訪問僅限于方法內或者該作用域內热押。

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部內部類
            int age =0;
        }
        return new Woman();
    }
}

注意,局部內部類就像是方法里面的一個局部變量一樣斤寇,是不能有public桶癣、protected、private以及static修飾符的娘锁。

匿名內部類:
匿名內部類應該是平時我們編寫代碼時用得最多的鬼廓,在編寫事件監(jiān)聽的代碼時使用匿名內部類不但方便,而且使代碼更加容易維護致盟。

下面這段代碼是一段Android事件監(jiān)聽代碼:

scan_bt.setOnClickListener(new OnClickListener() {         
    @Override
    public void onClick(View v) {
    
    }
});

這段代碼為按鈕設置監(jiān)聽器,這段代碼中的:

new OnClickListener() {
    public void onClick(View v) {
                 
    }
}

上面就是匿名內部類的使用尤慰。代碼中需要給按鈕設置監(jiān)聽器對象馏锡,使用匿名內部類能夠在實現(xiàn)父類或者接口中的方法情況下同時產生一個相應的對象,但是前提是這個父類或者接口必須先存在才能這樣使用伟端。

當然像下面這種寫法也是可以的杯道,跟上面使用匿名內部類達到效果相同:

private void setListener()
{
    scan_bt.setOnClickListener(new Listener1());       
    history_bt.setOnClickListener(new Listener2());
}
 
class Listener1 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
             
    }
}
class Listener2 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
             
    }
}

這種寫法雖然能達到一樣的效果,但是既冗長又難以維護责蝠,所以一般使用匿名內部類的方法來編寫事件監(jiān)聽代碼党巾。同樣的,匿名內部類也是不能有訪問修飾符和static修飾符的霜医。

匿名內部類是唯一一種沒有構造器的類齿拂。正因為其沒有構造器,所以匿名內部類的使用范圍非常有限肴敛,大部分匿名內部類用于接口回調署海。匿名內部類在編譯的時候由系統(tǒng)自動起名為Outter$1.class。一般來說医男,匿名內部類用于繼承其他類或是實現(xiàn)接口砸狞,并不需要增加額外的方法,只是對繼承方法的實現(xiàn)或是重寫镀梭。

靜態(tài)內部類:
靜態(tài)內部類也是定義在另一個類里面的類刀森,只不過在類的前面多了一個關鍵字static。靜態(tài)內部類是不需要依賴于外部類的报账,這點和類的靜態(tài)成員屬性有點類似研底,并且它不能使用外部類的非static成員變量或者方法埠偿,這點很好理解,因為在沒有外部類的對象的情況下飘哨,可以創(chuàng)建靜態(tài)內部類的對象胚想,如果允許訪問外部類的非static成員就會產生矛盾,因為外部類的非static成員必須依附于具體的對象芽隆。

public class Test {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
}
 
class Outter {
    public Outter() {
         
    }
     
    static class Inner {
        public Inner() {
             
        }
    }
}

內部類的使用場景和好處:
為什么在Java中需要內部類浊服?
總結一下主要有以下四點:

  • 每個內部類都能獨立的繼承一個接口的實現(xiàn),所以無論外部類是否已經繼承了某個(接口的)實現(xiàn)胚吁,對于內部類都沒有影響牙躺。內部類使得多繼承的解決方案變得完整
  • 方便將存在一定邏輯關系的類組織在一起,又可以對外界隱藏
  • 方便編寫事件驅動程序
  • 方便編寫線程代碼

認為第一點是最重要的原因之一腕扶,內部類的存在使得Java的多繼承機制變得更加完善

補充:
關于成員內部類的繼承問題孽拷。一般來說,內部類是很少用來作為繼承用的半抱。但是當用來繼承的話脓恕,要注意兩點:

  • 成員內部類的引用方式必須為 Outter.Inner 形式
  • 構造器中必須有指向外部類對象的引用,并通過這個引用調用super() (見下面代碼)
class WithInner {
    class Inner{
         
    }
}
class InheritInner extends WithInner.Inner {
      
    // InheritInner() 是不能通過編譯的窿侈,一定要加上形參
    InheritInner(WithInner wi) {
        wi.super(); //必須有這句調用
    }
  
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner obj = new InheritInner(wi);
    }
}

老師下午給的word請點我查看下載


每日一練:

課堂作業(yè):
沒留 暫無

課外練習:
課外作業(yè)點我查看


拓展閱讀:

1 - Java內部類的使用小結
2 - java提高篇(八)----詳解內部類
3 - java中的內部類總結

后記
世界上所有的追求都是因為熱愛
一枚愛編碼 愛生活 愛分享的IT信徒
— hongXkeX

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末炼幔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子史简,更是在濱河造成了極大的恐慌乃秀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圆兵,死亡現(xiàn)場離奇詭異跺讯,居然都是意外死亡,警方通過查閱死者的電腦和手機殉农,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門刀脏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人超凳,你說我怎么就攤上這事火本。” “怎么了聪建?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵钙畔,是天一觀的道長。 經常有香客問我金麸,道長擎析,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮揍魂,結果婚禮上桨醋,老公的妹妹穿的比我還像新娘。我一直安慰自己现斋,他們只是感情好喜最,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庄蹋,像睡著了一般瞬内。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上限书,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天虫蝶,我揣著相機與錄音,去河邊找鬼倦西。 笑死能真,一個胖子當著我的面吹牛,可吹牛的內容都是我干的扰柠。 我是一名探鬼主播粉铐,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卤档!你這毒婦竟也來了蝙泼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤裆装,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后倡缠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哨免,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年昙沦,在試婚紗的時候發(fā)現(xiàn)自己被綠了琢唾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡盾饮,死狀恐怖采桃,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情丘损,我是刑警寧澤普办,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站徘钥,受9級特大地震影響衔蹲,放射性物質發(fā)生泄漏。R本人自食惡果不足惜呈础,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一舆驶、第九天 我趴在偏房一處隱蔽的房頂上張望橱健。 院中可真熱鬧,春花似錦沙廉、人聲如沸拘荡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽珊皿。三九已至,卻和暖如春袱结,著一層夾襖步出監(jiān)牢的瞬間亮隙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工垢夹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溢吻,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓果元,卻偏偏與公主長得像促王,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子而晒,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法蝇狼,類相關的語法,內部類的語法倡怎,繼承相關的語法迅耘,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 一:java概述:1监署,JDK:Java Development Kit颤专,java的開發(fā)和運行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,654評論 0 11
  • 本文出自 Eddy Wiki 钠乏,轉載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 1,206評論 0 5
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法栖秕,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,227評論 0 2
  • 真的不是標題黨,觀影過程中幾次淚點爆發(fā)晓避,又是一部直擊人心的好作品簇捍。動畫片絕對不是一個娛樂業(yè)的產物,而是教育俏拱。它捧著...
    JessiayRen閱讀 665評論 0 1