天天看點

java基礎(三)繼承/多态/接口

這輩子沒辦法做太多事情,是以每一件都要做到精彩絕倫!

People can't do too many things in my life,so everything will be wonderful 

JDK API 1.6.0 中文版免費下載下傳位址:http://down.51cto.com/data/2300228

萬事萬物皆對象

繼承概述:

a,多個類中存在相同屬性和行為時,将這些内容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,隻要繼承那個類即可;

b,通過extends關鍵字可以實作類與類的繼承;

c,單獨的這個類(被繼承的類)稱為父類,基類或超類;這多個類(繼承類)可以成為子類或者派生類;

d,有了繼承以後,我們定義一個類的時候,可以在一個已經存在的類的基礎上,還可以定義自己的新成員。

繼承的好處:

a,提高了代碼的複用性;多個類相同的成員可以放到一個類中;

b,提高了代碼的維護性;如果功能的代碼需要修改,隻需要修改一處即可(雙刃劍);

c,讓類與類之間産生了關系,是多态前提;這也是繼承的一個弊端,類的耦合性太強。

設計原則:高内聚低耦合:内聚就是自己完成某件事情的能力;耦合就是類與類之間的關系。

java隻支援單繼承,不支援多繼承:一個類隻能有一個父類,不可以有多個父類;

java支援多層繼承

java繼承注意事項:

a,子類隻能繼承父類所有非私有的成員(成員方法和成員變量),這也展現了繼承的另一個弊端:打破了封裝性(隐藏屬性和實作方法,提供公共的通路方法)!

b,子類不能繼承父類的構造方法,但是可以通過super關鍵字去通路父類的構造方法。

c,不要為了部分功能而去繼承;

d,繼承中類之間提現的是:“is a”的關系;

水果和蘋果:蘋果是一種水果;學生和人,學生是人的一種;

繼承中成員變量的關系

查找變量順序:

在子類方法中通路一個變量:

a,首先在子類局部範圍找

b,然後在子類成員範圍找

c,最後在父類成員範圍找(不能通路父類局部範圍)

都找不到,報錯!(不考慮父類的父類)

super關鍵字:super代表父類存儲空間的辨別,可以了解為:父類引用

super用法(this):this/super.成員變量;this/super(); this/super.成員方法();

2.1.2.1 成員變量:

         a,子父類中的成員變量名稱不一樣時,是誰找誰

         b,子父類中的成員變量名稱一樣,子類方法通路變量查找順序:

                            1),在子類局部中找,有就用;

                            2),在子類的成員範圍找,有就用;

                            3),在父類的成員範圍找,有就用;都找不到,報錯

2.1.2.2 構造方法

a,子類的構造方法預設通路父類的無參構造方法:

因為子類會繼承父類中的資料,可能還會使用父類的資料。是以,子類初始化之前,一定要先完成父類資料的初始化。

每一個構造方法的第一條語句預設都是:super()

b,父類中如果沒有無參構造;

1),子類通過super去明确調用帶參構造;

2),子類通過this調用本身的其他構造

本類其他構造也必須首先通路了父類構造

3),一定要注意:

super(…)或者this(….)必須出現在第一條語句上

否則,就會有父類資料的多次初始化

2.1.2.3 成員方法:

a,子父類成員方法名稱不一樣

b,子父類成員方法名稱一樣

查找順序:子類—>父類,沒有報錯。(不考慮父類的父類的情況)

2.1.2.4 方法重寫:

方法重寫:子類中出現了和父類中相同的方法聲明,也被成為方法覆寫,方法複寫。

特點:如果方法名不同,就調用對應的方法;如果方法名相同,最終使用的是子類自己的。

方法重寫的應用:

當子類需要父類的功能,而功能主體子類有自己特有内容時,可以重寫父類中的方法,這樣,即沿襲了父類的功能,又定義了子類特有的内容。

方法重寫注意事項:

         a,父類中私有方法不能被重寫;

         b,子類重寫父類方法時,通路權限不能更低;

final:關鍵字是最終的意思,可以修飾類,成員變量,成員方法。

a,修飾類,類不能被繼承;

b,修飾變量,變量就變成常量,隻能被指派一次;

c,修飾方法,方法不能被重寫。

某一個事物,在不同時刻表現出來的不同狀态。

舉例:

    貓可以是貓的類型。貓 m= new 貓();

    同時貓也是動物的一種,也可以把貓稱為動物。

   動物d = new 貓();

多态的前提和展現:

a,有繼承關系;

b,有方法重寫;

c,有父類引用指向子類對象。

多态的分類:

                            a:具體類多态

                                     classFu {}

                                     classZi extends Fu {}

                                     Fuf = new Zi();

                            b:抽象類多态

                                     abstractclass Fu {}

                            c:接口多态

                                     interfaceFu {}

                                     classZi implements Fu {}

成員變量:編譯看左邊,運作看左邊;(父類)

成員方法:編譯看左邊,運作看右邊;(左父類,右子類(方法重寫))

構造方法:子類的構造會預設通路父類的構造,先初始化父類資料

靜态方法:編譯看左邊,運作看左邊。(父類)靜态和類相關,算不上重寫,通路的還是左邊!

為什麼通路成員方法時,執行子類;因為方法中有方法重寫。

多态繼承中的記憶體圖解:

java基礎(三)繼承/多态/接口

多态的好處:

a,提高了程式的維護性(由繼承保證)

b,提高了程式的擴充性(由多态保證)

多态的弊端

不能通路子類特有功能;多态轉型解決

向上轉型

從子到父

父類引用指向子類對象

向下轉型

從父到子

父類引用轉為子類對象

多态的問題了解:

         class孔子爹 {

                   publicint age = 40;

                   publicvoid teach() {

                            System.out.println("講解JavaSE");

                   }

         }

         class孔子 extends 孔子爹 {

                   publicint age = 20;

                            System.out.println("講解論語");

                   publicvoid playGame() {

                            System.out.println("英雄聯盟");

         //Java學習特别火,很多人來請孔子爹去講課,這一天孔子爹被請走了

         //但是還有人來請,就剩孔子在家,價格還挺高。孔子一想,我是不是可以考慮去呢?

         //然後就穿上爹的衣服,帶上爹的眼睛,粘上爹的胡子。就開始裝爹

         //向上轉型

         孔子爹 k爹 = new 孔子();

         //到人家那裡去了

         System.out.println(k爹.age); //40

         k爹.teach(); //講解論語

         //k爹.playGame();//這是兒子才能做的

         //講完了,下班回家了

         //脫下爹的裝備,換上自己的裝備

         //向下轉型

         孔子 k = (孔子) k爹;

         System.out.println(k.age);//20

         k.teach();//講解論語

         k.playGame();//英雄聯盟

多态中的對象變化記憶體圖解:

java基礎(三)繼承/多态/接口

抽象類概述:回想前面我們的貓狗案例,提取出了一個動物類。并且我們在前面也建立過了動物對象,其實這是不對的。

為什麼呢?因為,我說動物,你知道我說的是什麼動物嗎?隻有看到了具體的動物,你才知道,這是什麼動物。是以說,動物本身并不是一個具體的事物,而是一個抽象的事物。隻有真正的貓,狗才是具體的動物。同理,我們也可以推想,不同的動物吃的東西應該是不一樣的,是以,我們不應該在動物類中給出具體展現,而是應該給出一個聲明即可。

在Java中,一個沒有方法體的方法應該定義為抽象方法,而類中如果有抽象方法,該類必須定義為抽象類。

抽象類特點

抽象類和抽象方法必須用abstract關鍵字修飾

格式

abstract class 類名 {}

public abstract void eat();

抽象類不一定有抽象方法,有抽象方法的類一定是抽象類

抽象類不能執行個體化

那麼,抽象類如何執行個體化呢?

按照多态的方式,由具體的子類執行個體化。其實這也是多态的一種,抽象類多态。

抽象類的子類

要麼是抽象類

要麼重寫抽象類中的所有抽象方法

l 成員變量

    可以是變量

    也可以是常量

l 構造方法

    有構造方法,但是不能執行個體化

    那麼,構造方法的作用是什麼呢?

    用于子類通路父類資料的初始化

l 成員方法

    可以有抽象方法 限定子類必須完成某些動作

    也可以有非抽象方法 提高代碼複用性

抽象類的幾個小問題

                   A:抽象類有構造方法,不能執行個體化,那麼構造方法有什麼用?

                            用于子類通路父類資料的初始化

                   B:一個類如果沒有抽象方法,卻定義為了抽象類,有什麼用?

                            為了不讓建立對象

                   C:abstract不能和哪些關鍵字共存

                            a:final       沖突

                            b:private沖突

                            c:static無意義

看貓狗案例:狗一般就是看門,貓一般是寵物。但是,現在很多馴養師,可以訓練出:貓鑽火圈,狗跳高等等動作,這些并非貓狗天生的,屬于特殊訓練出來的。這些額外的動作定義到動物類中就不合适,也不适合直接定義到貓或狗中,因為隻有部分貓狗具備這些功能。是以,為了展現事物功能的擴充性,Java中就提供了接口來定義這些額外功能,并不給出具體實作,将來哪些貓狗需要被教育訓練,隻需要這部分的貓狗把這些額外的功能實作即可。

接口特點:

接口用關鍵字interface表示

格式:interface 接口名{}

類實作接口用implements表示

格式:class 類名 implements接口名{}

接口不能執行個體化

那麼接口如何執行個體化?--按照多态的方式,由具體的子類執行個體化。也是多态的一種,接口多态。

接口的子類

要麼重寫接口中的所有的抽象方法

成員變量:

隻能是常量

預設修飾符publicstatic final

構造方法

沒有,因為接口主要是擴充功能的,而沒有具體實作存在

成員方法

隻能是抽象方法

預設修飾符publicabstract

類與類,類與接口,接口與接口的關系

類與類

繼承關系,隻能單繼承,但是可以多層繼承

類與接口

實作關系,可以單實作,也可以多實作。還可以繼承一個類的同時實作多個接口

接口與接口

繼承關系,可以多繼承

抽象類與接口的差別

成員差別

抽象類:變量,常量;有抽象方法,非抽象方法

接口:常量,抽象方法

關系差別:

類與類 繼承,單繼承,多層繼承

類與接口 實作,多實作

接口與接口  繼承,多繼承

設計理念差別

抽象類 被繼承展現的是:“is a”的關系。共×××。

接口 被實作展現的是:“like a”的關系。擴充功能。

教練和運動員案例:

    乒乓球運動員和籃球運動員。

    乒乓球教練和籃球教練。

    為了出國交流,跟乒乓球相關的人員都需要學習英語。

    分析,這個案例中有哪些抽象類,哪些接口,哪些具體類。

java基礎(三)繼承/多态/接口

形式參數:

基本類型 需要什麼就是什麼

引用類型:

                            類:需要的是該類的對象

                            抽象類:需要的是該抽象類的子類對象

                            接口:需要的是接口的子類對象

傳回值類型

基本類型 傳回什麼就用什麼接收

引用類型

類:傳回的是該類對象

抽象類:傳回的是該類的子類對象

接口:傳回的是接口的子類對象

鍊式程式設計  舉例:new PersonDemo().getPerson().show();

包的概述

其實就是檔案夾

作用:對類進行分類管理

包的劃分:按照功能劃分;按照子產品劃分

包的格式:

package 包名;多級包用.分開即可

注意事項:

package語句必須是程式的第一條可執行的代碼

package語句在一個java檔案中隻能有一個

如果沒有package,表示無包名

帶包的類的編譯和運作

手動式

a,javac編譯目前類檔案;

b,手動建立包對應的檔案夾;

c,把a步驟的class檔案放在b步驟的最終檔案夾下;

d,通過java指令執行。注意:需要帶包名稱的執行:java cn.xxx.HelloWorld

自動式

a,javac編譯的時候帶上-d即可:javac –d HelloWorld.java

b,通過java指令執行。和手動式一樣

導包概述:

不同包下的類之間的通路,我們發現,每次使用不同包下的類的時候,都需要加包的全路徑。比較麻煩。這個時候,java就提供了導包的功能

導包格式

import 包名;

注意: 這種方式導入是到類的名稱;雖然可以最後寫*,但是不建議

package.import.class有沒有順序關系(面試題)

public

protected

預設

private

同一類中

同一包子類,其他類

不同包

子類

其他類

注意這四種修飾符在任意時刻隻能出現一種!

5.3.3.1 常見的修飾符

(1)分類:

                   權限修飾符:private,預設,protected,public

                   狀态修飾符:static,final

                   抽象修飾符:abstract

(2)常見的類及其組成的修飾

                   類:

                            預設,public,final,abstract

                            常用的:public

                   成員變量:

                            private,預設,protected,public,static,final

                            常用的:private

                   構造方法:

                            private,預設,protected,public

                   成員方法:

                            private,預設,protected,public,static,final,abstract

内部類:把類定義在其他類的内部,這個類就被稱為内部類。

内部類的通路特點:

内部類可以直接通路外部類的成員,包括私有

外部類要通路内部類的成員,必須建立對象

内部類位置:按照内部類在類中定義的位置不同,可以分為兩種格式:

成員位置(成員内部類)

局部位置(局部内部類)

 成員内部類:

非靜态的成員内部類,成員隻能是非靜态的;

通路方法:外部類名.内部類名對象名 = new 外部類名.new 内部類名();

内部類被靜态修飾後的方法,有靜态和非靜态之分。他們的通路和不用靜态是不一樣的。

被靜态修飾的成員内部類隻能通路外部類的靜态成員:

通路非靜态方法:外部類名.内部類名 對象名=new 外部類名.内部類名();

通路靜态方法:上面建立的對象通路,或外部類名.内部類名.方法名();

         成員内部的常見修飾符:

private 為了保證資料的安全性;

static 為了通路的友善性

5.3.4.2 局部内部類

可以直接通路外部類的成員

可以建立内部類對象,通過對象調用内部類方法,來使用局部内部類功能

局部内部類通路局部變量注意事項:必須被final修飾!

因為局部變量(棧記憶體中)會随着方法的調用完畢而消失,這個時候,局部對象并沒有馬上從堆記憶體中消失,還要使用這個變量,為了讓資料還能繼續被使用,就用final修飾,在堆記憶體中存儲的就是一個常量值!常量池存在于方法區中?

 匿名内部類

就是内部類的簡化寫法。

前提是:存在一個類或者接口。這裡的類可以是具體類也可以是抽象類。

格式:new 類名或接口名(){重寫方法;}

本質:是一個繼承子類或者實作了接口的子類匿名對象;

應用場景:首先回顧方法的形式參數是引用類型的情況,重點是接口的情況,我們知道這裡需要一個子類對象。而匿名内部類就是一個子類匿名對象,是以,可以使用匿名内部類進行改進。

java基礎(一)java文法

java基礎(二)面向對象

java基礎(三)繼承/多态/接口

java基礎(四)常用類/算法

java基礎(五)集合/IO流/異常

java基礎(六)多線程/設計模式

java基礎(七)網絡程式設計/反射/動态代理