1. 程式人生 > >04-java面向物件

04-java面向物件

java面向物件

 

面向過程開發:

  其實就是面向具體的每一個步驟和過程,把每一個步驟和過程完成,然後有這些功能方法相互呼叫,完成需求

  代表語言:C語言

面向物件是基於面向過程的程式設計思想

  面向過程:強調的是每一個功能的步驟

  面向物件:強調的是物件,然後由物件去呼叫功能

面向物件的特點:

  1:是一種更符合我們思想習慣的思想

  2:可以將複雜問題簡單化

  3:將我們從執行者變成指揮者

  舉例:

  買電腦:

    面向過程:   瞭解電腦

          瞭解需求

          對應引數資訊 

          去電腦城買電腦

          討價還價

          買回電腦

    面向物件:

        我要買電腦,叫人去給我買 ,別人給我買回來

  洗衣服:

    面向過程:脫衣服 找洗衣盆 放洗衣粉 加點水 戳衣服 清洗衣服 擰乾 晾衣服

    面向物件:脫衣服 開啟洗衣機 扔衣服 一鍵即可 晾起來

    

面向物件開發:

  就是不斷的建立物件,使用物件,指揮物件做事情

面向物件設計:

  其實就是在管理與維護物件之間的關係

面向物件特徵:

  封裝

  繼承

  多型

 

現實世界如何描述一個事物:

  學生

    姓名,性別 年齡

    學習 吃飯 水蕨

  屬性:該事物的資訊

  行為:該事物能夠做什麼

學習程式語言,是為了模擬現實世界的事物的

java中最基本的單位是:類

將事物用類體現出來

事物和類的對應關係:

  事物:            類:

      屬性            成員變數

      行為            成員方法

 

類:是一組相關的屬性和行為的集合。是一個抽象的概念

物件:是該類事物的具體表現形式。具體存在的個體

 

舉例;

  學生:類

  班長:物件

定義類:其實對應類就是定義類的成員變數與成員方法

 

如何使用:
  建立物件使用
如何建立:
  格式:類名 物件名 = new 類名()
如何使用成員變數:
  物件名.變數名
如何使用成員方法:
  物件名.方法名(引數)

 

 

成員變數與成員變數的區別:

  1:在類中的的位置不同

    成員變數:在類中方法外

    區域性變數:在方法定義中或者方法宣告

  2:在記憶體中的位置不同

    成員變數:堆記憶體

    區域性變數:棧記憶體

  3:生命週期不同

    成員變數:隨著物件的建立而存在,隨著物件的消失而消失

    區域性變數:隨著方法的呼叫而存在,隨著方法的呼叫完畢而消失

  4:初始化值不同:

    成員變數:有預設初始化值

    區域性變數:沒有預設初始化值,必須定義,賦值,然後才能使用

  注意:

    區域性變數名稱可以和成員變數名稱一樣,在方法中使用的時候,採用的是就近原則。

 

形式引數問題:

  基本型別:形式引數的改變不影響實際引數

  引用型別:形式引數的改變直接影響實際引數

 

類和陣列是引用型別

 

 

匿名物件:

  就是沒有名字的物件

  new Student();

匿名物件的應用場景:

  1:呼叫方法:僅僅呼叫一次時候

     呼叫多次時不適合

     匿名物件好處:

      匿名物件呼叫完就是垃圾,可以被垃圾回收器回收

 

    匿名物件呼叫方法:

      new Student().show();

  2:匿名物件可以作為實際引數傳遞

 

 

測試類一般只建立物件,呼叫方法

 

資料判斷不可以在成員變數位置,因為做資料校驗,必須依靠邏輯語句,邏輯語句應該定義在方法中

 

 

封裝:是指隱藏物件的屬性和實現細節,僅對外提供公共訪問方式

  好處:

    隱藏實現細節,提供公共的訪問方式

    提高了程式碼的複用性

    提高安全性

  封裝原則:

    將不需要對外提高的內容都隱藏起來

    把屬性隱藏,提供公共方法對其訪問  

 

 

private關鍵字:

  是一個許可權修飾符

  可以修飾成員(成員變數和成員方法)

  被private修飾的成員只能在本類中才能訪問 

 private的應用:

  把成員變數用private修飾

  提供對應的getXxx()和setXxx()方法

this關鍵字:  

  代表所在類的物件引用

  方法被哪個物件呼叫,this就代表那個物件

  什麼時候使用this

    區域性變數隱藏成員變數

 

 

構造方法作用:

  給物件的資料進行初始化

構造方法格式:

  方法名與類名相同

  沒有返回值型別,連void都沒有

  沒有具體的返回值

注意事項:

  如果你不提供構造方法,系統會給出預設構造方法

  如果你提供了構造方法,系統將不再提供

  構造方法也是可以過載的

 

給成員變數賦值:

  1:setXxx()

  2:構造方法

 

類的組成:

  成員變數

  構造方法

  成員方法

方法具體劃分:

  根據返回值:

    有明確返回值的方法

    返回void型別的方法

  根據形式引數:

    無參方法

    帶參方法

 

一個基本類的標準程式碼寫法:

  類:

    成員變數

    構造方法

      無參構造方法

      帶參構造方法

    成員方法:

      getXxx()

      setXxx()

  給成員變數賦值的方式:

    無參構造方法+setXxx()

    帶參構造方法

 

 

static關鍵字:可以修飾成員變數,也可以修飾成員方法

  特點:

    1;隨著類的載入而載入

      回想main方法

    2:優先於物件存在

      3:被類的所有物件共享  

    4:可以通過類名呼叫(推薦使用)

      其實它本身也可以通過物件名呼叫

    靜態修飾的內容議案稱其為:與類相關的,類成員

   注意事項:  

    1:在靜態方法中沒有this關鍵字的

       靜態是隨著類的載入為載入,this是隨著物件的建立而存在

       靜態比物件先存在

    2:靜態方法只能方法訪問靜態的成員變數和靜態成員方法

      靜態方法:

        成員變數:只能訪問靜態變數

        成員方法:只能方法靜態成員方法

      非靜態方法:

        成員變數:可以是靜態的木葉可以非靜態的

        成員方法:可以是靜態的成員方法,也可以是非靜態的成員方法

靜態變數和成員的區別:

所屬不同

  靜態變數屬於類,也稱為類變數

  成員變數屬於物件,也稱為例項變數

記憶體中的位置不同:

  靜態變數儲存於方法區的靜態區

  成員變數儲存於堆記憶體

記憶體出現時間不同:

  靜態變數隨著類的載入而載入,隨類的消失而消失

  成員變數隨著物件的創而存在,隨著物件的消失而消失

呼叫不同:

  靜態變數可以通過類名呼叫,也可以通過物件呼叫

  成員變數只能通過物件呼叫

 

main方法的格式:

  public:公共的,訪問許可權是最大的,由於main方法是被jvm呼叫,所以許可權要夠大

  static:靜態的,不需要建立物件,通過類名就可以,方便jvm呼叫

  void:方法的返回值是返回給呼叫者,而main方法是被jvm呼叫,返回內容給jvm沒有意義

  main:是一個常見的方法入口。幾乎語言都是以main作為入口

  String[] args:這是一個字串陣列

    是早期為了接受鍵盤資料的

      格式:java 類名 string... java

 

測試類的作用:建立其他類的物件,呼叫其它類的功能

在同一個資料夾下,類定義在兩個檔案中和呼叫在一個檔案中其實一樣的

方法改為靜態後,就可以直接通過類名呼叫

 

如何製作說明書(幫助文件)
1:寫一個工具類
2:對這個類加入文件註釋
3:用工具解析文件註釋
javadoc工具
4:格式
javadoc -d 目錄 -author -version ArryTool.java
目錄:寫一個資料夾的路徑
製作幫助文件出錯:
找不到可以文件化的公共或受保護的類:告訴我們類的許可權不夠

 

java.lang包下的類不需要匯入,其它的全部需要匯入

 

 

看類的版本

類的結構:

  成員變數  欄位摘要

  構造方法  構造方法摘要

  成員方法  方法摘要

學習構造方法

  有構造方法  就建立物件

  沒有構造方法 成員可能都是靜態的

看方法

  左邊:

    是否靜態:如果靜態,可以通過類名呼叫

    返回值型別:人家 返回什麼,就用什麼接收

  右邊:

    看方法名:方法名稱不要寫錯

    引數列表:人家要什麼,就給什麼;人家要幾個,就給幾個

    

java程式碼塊:

  java中,使用{}括起來的程式碼被稱為程式碼塊

  根據其位置和宣告不同,分為:

    區域性程式碼塊:區域性位置,用於限定變數的聲生命週期。及早釋放,提高記憶體利用率

    構造程式碼塊:在類中的成員位置,用{}括起來的程式碼,每次呼叫構造方法前,都會先執行構造程式碼塊

      作用:可以把多個構造方法中的共同程式碼放到一起,對物件進行初始化

    靜態程式碼塊:在類中的成員位置,用{}括起來的程式碼,只不過它用static修飾

      作用:一般是對類進行初始化

    同步程式碼塊:

執行順序:

  靜態程式碼塊   --   構造程式碼塊   --     構造方法

  靜態程式碼塊:執行一次      

  構造程式碼塊:每次呼叫構造方法都執行

 

java繼承:

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

  格式:class 子類名 extends 父類名{}

  單獨這個類稱為父類,基類,或者超類;這多個類稱為子類或者派生類

  在已經存在類的基礎上,還可以定義自己的新成員

繼承的好處:

  提高了程式碼的複用性

    多個類相同的成員可以放到一個類中

  提高了程式碼的維護性

    如果程式碼功能需要修改,修改一處即可

  讓類與類之間產生了關係,是多型的前提

    其實這也是繼承的一個弊端,類的耦合性很強

 

開發原則:低耦合,高內聚

      耦合:類與類的關係

      內聚:就是自己完成事情的能力

 

java繼承特點:

  java只支援單繼承,不支援多繼承

    一個類只能有一個父類,不可以有多個父類

  java支援多層繼承(繼承體系)

  class A{}

  class B extends A{}

  class C extends C{}

java繼承注意事項:

  子類只能繼承父類所有非私有的成員(成員變數,成員方法)

    其實這也體現了繼承的另一個弊端,打破了封裝性

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

  不要為了部分功能去繼承

  繼承其實體現的是一種關係:"is a";採用假設法

  

  繼承中成員變數的關係:在子類中訪問一個變數的查詢順序

    名字一樣

    ·1:在子類中的區域性範圍找,有就使用

    2:在子類的成員範圍找,有就使用

    3:在父類的成員範圍找,有就使用

    4:如果還找不到,就報錯    

 

super的用法和this很像

  this代表本類對應的引用

  super代表父類儲存空間的標識

  用法:

  訪問成員變數:

    this.成員變數 呼叫本類的成員變數

       super.成員變數 呼叫父類的成員變數

  訪問構造方法

    this(...)  呼叫本類的構造方法

    super(...)  呼叫父類的構造方法

  訪問成員方法

    this.成員方法 呼叫本類的成員方法

    super.成員方法  呼叫父類的成員方法

繼承中構造方法的關係:

  子類中所有的構造方法預設都會訪問父類中的空引數的構造方法

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

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

this和super的區別:

 

繼承中構造方法的注意事項:

  如果父類沒有無參構造方法,子類的構造方法會出現什麼現象?子類報錯

  怎麼解決

  A:在父類中加一個無參構造方法

  B:通過使用super關鍵字去顯示的呼叫父類的帶參構造方法

  C:子類通過桃紅色去呼叫本類的其他構造方法

    子類中一定要有一個去訪問了父類的構造方法,否則父類資料就沒有初始化

  注意事項:

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

 

 繼承中成員方法關係:

  子類中的方法和父類中的方法宣告一樣

    通過子類呼叫方法:

      1:先找子類中,看有沒有這個方法,有就使用

      2:再看父類中,有沒有這個方法,有就使用

      3:如果沒有就報錯

方法過載:本類中出現的方法名一樣,引數列表不同的方法,與返回值無關

 

方法重寫:子類中出現了和父類中方法宣告一模一樣的方法宣告,也叫方法覆蓋,方法複寫

 

方法重寫的應用:

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

方法重寫的注意事項:

  1:父類中的私有方法不能被重寫:父類私有方法子類無法繼承

  2:子類重寫父類方法時,訪問許可權不能更低:最好一致

  3:父類靜態方法。子類也必須通過靜態方法進行重寫(其實不算重寫,多型講)

  子類重寫方法的時候,最好宣告一模一樣

override:方法重寫

overload:方法過載

 

API(Apilication Programming Interface)

應用程式程式設計介面(幫助文件)

 

由於繼承中方法有一個現象:方法重寫

所以父類的功能會被子類覆蓋

java final關鍵字:最終的意思。常見的是它可以修飾類,方法,變數。

final的特點:

  1:修飾類的特點:該類不能被繼承。

  2:修飾方法的特點:該方法不能被重寫

  3:修飾變數的特點:該變數不能被重新賦值。因為這個變數其實是常量

常量:

  1:字面值常量:"hell0",10,true

  2:自定義常量:final int x = 5;

 

final修飾區域性變數的問題:

  基本型別:基本型別的值不能發生改變

  引用型別:引用型別的地址值不能發生改變,該物件的堆記憶體的值可以改變的

final修飾變數的初始化時機:

  1:被final修飾的變數只能被賦值一次

  2:在構造方法完畢前。(非靜態的常量)

 

java多型

多型:某一個事物,在不同時刻表現出來的不同狀態

多型前提和體現:

  1:有繼承關係或者實現關係

  2:有方法重寫

    其實沒有也是可以的,但是如果沒有這個就沒有意義

  3:有父類或者父介面引用指向子類物件

    Fu f = new Zi();

多型的分類:

  1:具體類多型:

    class Fu{}

    class Zi extends Fu{}

    Fu f = new Zi();

  2:抽象類多型

    abstract class Fu{}

    class Zi extends Fu{}

    Fu f =new Zi();

  3:介面多型

    interface Fu{}

    class Zi implements Fu{}

    Fu f = new Zi();

多型中成員的訪問特點:

  1:成員變數

    編譯看左邊,即看Fu類中的成員變數

    Fu f = new Zi();

    執行看左邊

  2:構造方法

    建立子類物件的時候,訪問父類的構造方法,對父類的資料進行初始化

  3:成員方法

    編譯看左邊,執行看右邊(方法存在覆蓋)

  4:靜態方法

    編譯看左邊,執行看右邊(靜態和類相關,算不上重寫,所以訪問還是左邊的)

  

多型的好處:

  1:提高了程式碼的維護性(繼承保證)

  2:提高了程式碼的拓展性(由多型保證)

多型的弊端:

  不能使用子類的特有功能

  怎麼使用:

    Fu f = new Zi();

    方式1:建立子類物件呼叫方法即可(很多時候不合理,而且佔記憶體)

    方式2:Zi z = (Zi)f;

        z.show();

        z.method()

      把父類的的引用強制轉換為子類的引用。(向下轉換)

多型物件間的轉型問題:

  向上轉型:

    Fu f = New Zi();

  向下轉型:

    Zi z = (Zi)f; 要求改f必須是能夠轉換為Zi的

 

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

抽象類的特點:

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

  2:抽象類中不一定有抽象方法,但有抽象方法的類必須定義為抽象類

  3:抽象類不能例項化

    因為它不是具體的

    抽象類有構造方法,但是不能例項化,用於子類訪問父類資料的初始化

  4:抽象類的子類

    a:如果不想重寫抽象方法,該子類是一個抽象類

    b:重寫所有的抽象方法,這個時候子類是一個具體的類

  抽象類的例項化其實靠具體的子類實現的。是多型的方式

 

抽象類的成員特點:

  成員變數:既可以是常量,也可以是變數

  構造方法:有構造方法,不能例項化

        作用:用於子類訪問父類資料的初始化

  成員方法:既可以是抽象的,也可以是非抽象的

 

抽象類的成員方法特性:

  1:抽象方法,強制要求子類做的事情

  2:非抽象方法,子類繼承的事情,提高程式碼的複用性

abstract不能那些關鍵字共存:

  private 衝突 

  final 衝突

  static 無意義

 

 

 

介面:為了體現事物功能的拓展性,java中就提供了介面來定義這些額外功能,並不給出具體實現,將來那些類需要這些功能,只需這些類實現額外功能即可

 

介面特點:

  1:介面用關鍵字interface表示

    interface 介面名{}

  2:類實現介面用implements表示

    class 類名 implements 介面名{}

   

  3:介面不能例項化
    那麼,介面如何例項化
    按照多型的方式來例項化
    由此可見:
    1:具體類多型(幾乎沒有)
    2:抽象類多型(常用)
    3:介面多型(最常用)
    4:介面的子類
      1:可以是抽象類,但意義不大
      2:可以是具體類。要重寫介面中的所有抽象方法。(推薦方案)

介面成員特點:

  成員變數:只能是常量,並且是靜態的

        預設修飾符:public static final(建議自己手動給出)

  構造方法:介面沒有構造方法

  成員方法:只能是抽象方法

        預設修飾符:public abstract

所有的類都預設繼承自一個類:Object

 

類與類的關係:繼承關係,只能單繼承,可以多層繼承
類與介面:
  實現關係,可以單實現,也可以多實現
  並且還可以在繼承一個類的同時實現多個介面
介面與介面:
  繼承關係:可以單繼承,也可以多繼承。

 

抽象類和介面的區別:
1:成員區別
抽象類:
成員變數:可以變數,也可以常量
構造方法:有
成員方法:可以抽象,也可以不抽象
介面:
成員變數:只可以是常量
成員方法:只可以抽象
2:關係區別
類與類:
繼承,單繼承
類與介面:
實現,單實現,多實現
介面與介面:
繼承,單繼承,多繼承
3:設計理念區別
抽象類 被繼承體現的是:"is a"的關係。抽象類中定義的該繼承體系的共性功能。
介面 被實現體現的是:"like a"的關係。介面中定義的是該繼承體系的拓展功能。

 

形式引數:
基本型別:
引用型別:
  類名:(匿名物件時講過)需要的是該類的物件
  抽象類名:需要的是該抽象類的子類物件
  介面名:需要的是該介面的實現類物件

 

返回值型別
基本型別:
引用型別:
  類:返回的是該類的物件
  抽象類:返回的是該抽象類的子類物件
  介面:返回的是該介面的實現類物件

 

鏈式程式設計:每次呼叫完畢方法後,返回的是一個物件

  S1 s =new S1();

    //S2 s2 = s.getXxx();

    //s2.fun();

  s.getXxx().fun();

  

包:其實就是資料夾

  作用:

    把相同的類名放到不同的包中

    對類進行分類管理

  按功能分:

  按模組分:

 

包的定義:

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

 

  注意事項:

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

    2:package語句在一個java檔案中只能有一個

    3:如果沒有package,預設表示無包名

帶包的編譯和執行:

  1:手動式:

    a:編寫一個帶包的java檔案

    b:通過javac命令編譯該java檔案

    c:手動建立包名

    d:把b步驟的class檔案放到c步驟的最底層包

    e:回到和包根目錄在同一目錄的地方,然後執行

      帶包執行

      java cn.itcat.HelloWorld

  2:自動式:

    a:編寫一個帶包的java檔案

    b:javac編譯的時候帶上-d即可

      javac -d . HelloWorld.java

    c:回到和包根目錄在同一目錄的地方,然後執行

      帶包執行

      java cn.com.HelloWorld

 

不同包下類之間的訪問:

  導包概述:

  不同包之下的類之間訪問,我們發現,每次使用不同包下的類的時候,都需要加包的全路徑,比較麻煩

  這個時候。java就提供了導包的功能

導包格式

  import 包名;

  注意:

  這種方式匯入是到類的名字

  雖然可以最後可以寫*,但是不建議。

  import com.fengzelang.Test;開發中用誰導誰

 

  package>Import>class

  package:只能有一個

  import:可以有多個

  class:可以有多個,以後建議是一個

 

許可權修飾符:

  修飾符  本類  同一個包下(子類和無關類)   不同包下(子類)  不同包下(無關類)

  private  Y                    

  預設   Y    Y              

  protected   Y    Y              Y

  public    Y      Y                 Y        Y

  

 

類及其組成所使用的常見修飾符

  許可權修飾符:private,預設的,protected,public

  狀態修飾符:static,final

  抽象修飾符:abstract

  類:

    許可權修飾符:預設修飾符,public

    狀態修飾符:final

    抽象修飾符:abstract

    用的最多:public

  成員變數:

    許可權修飾符:private,預設的,protected,public

    狀態修飾符:static,final

    用的最多:private

  構造方法:

    許可權修飾符:private,預設的,protected,public

       用的最多:public

  成員方法:

    許可權修飾符:private,預設的,protected,public

    狀態修飾符:static,final

    抽象修飾符:abstract

    用的最多:public

  除此以外的組合規則:

      成員變數:public static final

    成員方法:public static

         public abstract

         public final

 

內部類概述:
  把類定義在其他類的內部,這個類就被稱為內部類

內部類的訪問特點:
  1:內部類可以訪問外部類的成員,包括私有
  2:外部類要訪問內部類的成員,必須建立物件。

內部類的分類:

  1:成員內部類

  2:區域性內部類

  成員內部類

    1:private為了資料的安全性

    2:static為了訪問 的方便性

    成員內部類不是靜態的:

      外部類名.內部類名 物件名 = new 外部類名.new 內部類名();

    成員內部類是靜態的:

      外部類名.內部類名 物件名 = new 外部類類名.內部類名();

    靜態內部類訪問的外部類資料必須用靜態修飾

    成員內部類被靜態修飾後的訪問方式是:

      格式:外部類名.內部類名 物件名 = new 外部類名.內部類名();

 

    注意:

      內部類和外部類沒有繼承關係

      通過外部類名限定this物件

    

    區域性內部類:

      1:可以直接訪問外部類的成員

      2:在區域性位置,可以建立內部類的物件,通過物件呼叫內部類方法,來使用區域性內部類功能

    區域性內部類訪問區域性變數的注意事項:

      1:區域性內部類訪問區域性變數必須用final修飾

        因為區域性變數會隨著方法的呼叫完畢而消失,這個時候,區域性物件並沒有立馬從堆記憶體中消失

        還要繼續使用哪個變數。為了讓資料還能繼續被使用,就用final。這樣。在堆記憶體中儲存的是常量

        

匿名內部類:

  就是內部類的簡化寫法      

  前提:存在一個介面或者類

      這裡的類可以是具體類也可以是抽象類

  格式:

    new 類名或者介面(){

      重寫方法;

  }

  本質:

    是一個繼承了該類或者實現了該介面的子類匿名物件

    interface Inter{

      public abstract void show();

    }

    class Outer{

      public void method(){

        new Inter(){

          public void show(){

            System.out.println("show");

          }

        }.show();//物件呼叫方法

      }

    }

    //多個方法很難呼叫

    interface Inter{

      public abstract void show();

      public abstract void show2();

    }

    class Outer{

      public void method(){

        Inter i = new Inter(){//多型

          public void show(){

            System.out.println("show");

          } 

          public void show2(){

            System.out.println("show2");

          }

        };

        i.show();

        i.show2();

      }

    }

 

匿名內部類在開發中使用: