java基礎(chǔ)篇——面向?qū)ο?/font>

作者:xcbeyond
瘋狂源自夢(mèng)想,技術(shù)成就輝煌!微信公眾號(hào):《程序猿技術(shù)大咖》號(hào)主,專注后端開發(fā)多年,擁有豐富的研發(fā)經(jīng)驗(yàn),樂于技術(shù)輸出、分享,現(xiàn)階段從事微服務(wù)架構(gòu)項(xiàng)目的研發(fā)工作,涉及架構(gòu)設(shè)計(jì)、技術(shù)選型、業(yè)務(wù)研發(fā)等工作。對(duì)于Java、微服務(wù)、數(shù)據(jù)庫、Docker有深入了解,并有大量的調(diào)優(yōu)經(jīng)驗(yàn)。

引言:

        面向?qū)ο蟮乃枷胝荍ava學(xué)習(xí)的核心部分,要是沒有搞懂面向?qū)ο?,那么就稱不上學(xué)過Java,因此,搞懂面向?qū)ο笫侵陵P(guān)重要的。對(duì)于初學(xué)者而言,首次接觸面向?qū)ο髸r(shí),總感覺怪怪的,不知道究竟在干什么(我剛開始接觸也是這種感覺,漸漸的就找到感覺了),這其實(shí)都是正?,F(xiàn)象的,不然怎么有人說他是很抽象的啊。面向?qū)ο?,簡單的理解就是把一切事物按照它自己本有存在的特征、屬性通過自然組織語言組織起來,然后再用編程語言來實(shí)現(xiàn)。例如:人(類)本該就分有性別(男、女)、年齡、姓名等屬性特征,然對(duì)于每一個(gè)而言,他們往往具體不同的這些屬性特征值,于是就從“人”(類)這個(gè)類別中具體出來了每個(gè)人,即:類的實(shí)例化得到了對(duì)象。就可以對(duì)象他們進(jìn)行相應(yīng)的操作了。

面向?qū)ο?OO):

         按照東西的特征和自然組織形式, 進(jìn)行軟件開發(fā)過程的組織, 是一個(gè)開發(fā)過程的方法論。

 

學(xué)習(xí)面向?qū)ο?

      - 學(xué)習(xí)如何用OO語法描述事物的特征和自然組織形式.

      - 學(xué)習(xí)面向?qū)ο笏季S的前提是樸素的哲學(xué)邏輯.

            如: 多態(tài), 抽象概念的具體實(shí)現(xiàn)是多態(tài)的,

             如:美女是多態(tài)的!

 

一、類(Class):

       它是一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu),是把一類相似或相關(guān)聯(lián)數(shù)據(jù)的相關(guān)操作封裝在一起的一個(gè)集合。

  1、類是用來描述一個(gè)領(lǐng)域模型中的具體概念(名詞)的。

  2、領(lǐng)域模型: 一個(gè)應(yīng)用軟件業(yè)務(wù)范疇, 也叫業(yè)務(wù)模型.

  3、屬性: 描述具體概念(事物)的特征.

    如:<圖書館管理系統(tǒng)>中的概念: 書 Book

        書的特征: 書號(hào), 書名, 編號(hào), 作者, 價(jià)格...

 

Java中類的寫法(語法)如下:

 修飾詞 class 類名{

   修飾詞 類型 屬性;

  修飾符 返回值類型  方法名 {

      //  方法體(實(shí)現(xiàn)類的相關(guān)操作)

      }

  }

如:

     public class Book{
          int id;
          String name;
          String[] authors;
          String isbn;
          double price;
      }


 

二、對(duì)象:

  1、      對(duì)象是類的具體實(shí)例!

           比 如,書Book這個(gè)類,它只是代表了一類,你卻不知道它到底是什么書,但你只知道它擁有哪些特點(diǎn)屬性,即書名、書號(hào)、作者、書價(jià)等(類屬性)信息,為了對(duì)書Book這個(gè)類具體化,就引出了“對(duì)象”的概念,因此,對(duì)象就是類的具體實(shí)例。如:《山楂樹之戀》是一本書,《和空姐同居的日子》是一本書,他們屬于Book類的兩個(gè)不同的對(duì)象。

          對(duì)象的創(chuàng)建是通過“new”運(yùn)算符進(jìn)行實(shí)例化的,即:

                      

              Book book = new Book();//book:引用 new Book():對(duì)象

        看到這里,你或許還是一頭霧水,請(qǐng)不必?fù)?dān)心,先暫時(shí)記住就行了,隨后你就會(huì)徹底明白了。new Book()它是真正的在內(nèi)存中(準(zhǔn)確的說是在“堆”內(nèi)存中)創(chuàng)建了一個(gè)Book類的對(duì)象,此時(shí)在“?!敝袆?chuàng)建了一個(gè)Book類型(類也屬于一種數(shù)據(jù)類型,一種引用類型中的“類類型”)的引用變量book,最終將變量book的地址指向了new Book()創(chuàng)建的對(duì)象。<這里地址指向關(guān)系,是隱含存在的一種指針,可以這么理解,僅供理解而已。但java卻是不存在指針的哦!>   。關(guān)于“堆”、“棧”可以參考《java核心內(nèi)容——分配管理》了解。

     引用:是指向具體對(duì)象的句柄,相當(dāng)于自然語言的代詞。   

       1> 代詞本身不是對(duì)象,代詞引用了一個(gè)具體對(duì)象。

        2> 在特殊情況下引用(代詞)可能指空。

        3> 經(jīng)常簡單的敘述事物時(shí)候,不嚴(yán)格區(qū)別引用與對(duì)象。

       如:  

       Book book = new Book();//book:引用   new Book():對(duì)象  
     
        book.name = "月子";
     
       book.authors = new String[]{"白云","黑土"};
     
       book = null;//book引用null  
     
     

      4>引用是null時(shí)候,訪問屬性或方法時(shí)候會(huì)出現(xiàn): 空指針異常

     如:

    book = null;
     
    System.out.println(book.name);//異常   
     

2、構(gòu)造器(構(gòu)造方法):

       在上面語句Book   book  =   new  Book()中,或許對(duì)用new  Book()創(chuàng)建對(duì)象時(shí),并不知道其真正的含義,其中Book()就是一個(gè)Book類的一個(gè)構(gòu)造器(特殊的方法),用它來對(duì)對(duì)象的屬性進(jìn)行初始化。

構(gòu)造器的使用:

 1>、聲明在類內(nèi)部, 方法名與類名一致的方法叫構(gòu)造方法, 構(gòu)造方法不能聲明返回值類型。

 2>、構(gòu)造方法可以包含參數(shù), 參數(shù)一般是創(chuàng)建對(duì)象實(shí)例,必須依賴的條件(前提條件)。

如:

    public Book(int id,String name,String isbn) {
     
    this.id = id;
     
    this.name = name;
     
    this.isbn = isbn;
     
    }
     

  3>、構(gòu)造方法經(jīng)常會(huì)重載

        方法重載:方法的重新書寫,即重載

               - 方法名一樣

              - 方法參數(shù)不一樣

 

默認(rèn)構(gòu)造器:

            對(duì)于每一個(gè)類都會(huì)存在一個(gè)構(gòu)造器的,只是有些是使用的默認(rèn)構(gòu)造器而已,沒有顯式的顯示出來。

  1>、如果類沒有聲明任何構(gòu)造器,Javac自動(dòng)提供一個(gè)默認(rèn)構(gòu)造器, 無參數(shù)默認(rèn)構(gòu)造器。

  2>、如果提供構(gòu)造器聲明, Javac將不再提供默認(rèn)構(gòu) 造器。

如:(這個(gè)程序只是為了說明默認(rèn)構(gòu)造器而已,沒有其他實(shí)際價(jià)值)

    /**
     * 默認(rèn)構(gòu)造器的演示
     * @author xcbeyond
     *
     */
    public class ConstructorDemo {
        public static void main(String[] args) {
            Foo foo = new Foo();
            //Goo goo = new Goo();//錯(cuò)誤,沒有參數(shù)的構(gòu)造器
            //System.out.println(foo.a+","+goo.a);
            //A 、編譯錯(cuò)誤         B、 1,0   C、 1,1  D、
        }
    }
    class Foo {//沒有顯式的顯示構(gòu)造器,即使用默認(rèn)構(gòu)造器(無參構(gòu)造器)
        int a = 1;
    }
    class Goo{//沒有無參構(gòu)造器了
        int a ;
        public Goo(int a) {//默認(rèn)無參構(gòu)造器被重載成為了一個(gè)有參構(gòu)造器
            this.a = a;
        }
    }

 

new運(yùn)算: 創(chuàng)建對(duì)象實(shí)例,如: Book book = new Book();

  1、根據(jù)類的屬性在堆中分配對(duì)象空間。






  2、根據(jù)參數(shù)類型調(diào)用構(gòu)造器。

  3、new運(yùn)算返回對(duì)象的引用地址。

 

對(duì)象的創(chuàng)建過程:

  1、根據(jù)類的屬性在堆中分配對(duì)象空間,并且自動(dòng)初始化。

  2、根據(jù)參數(shù)類型調(diào)用構(gòu)造器。

 

this:

  最大的作用就是讓類中一個(gè)方法訪問該類的另一個(gè)方法或?qū)傩浴his可以代表任何對(duì)象。

   - this 是對(duì)當(dāng)前對(duì)象的引用, 是當(dāng)前對(duì)象本身。

   - 可以使用this明確的訪問當(dāng)前對(duì)象的屬性或者方法。

   - this() 是調(diào)用本類的其他構(gòu)造器, 可以使用構(gòu)造器的重用, 簡化代碼的實(shí)現(xiàn).

   - this() 必須寫在構(gòu)造器的第一行!

    如:public Book(int id ,String name) {
                //System.out.print(id);//錯(cuò) ,this()必須寫在第一行
            this(id,name,null);
        }
        public Book(int id,String name,String isbn) {
            this.id = id;
            this.name = name;
            this.isbn = isbn;
        }


 

java方法參數(shù)的傳遞規(guī)則:

             參數(shù)傳遞方式只有一種:值傳遞。值傳遞就是將實(shí)際參數(shù)值得副本(復(fù)制品)傳入方法內(nèi),而參數(shù)本身不會(huì)受到任何影響。

 1、基本類型就是其中值的復(fù)制, 引用類型是引用值(地址)的復(fù)制。

 2、 變量的值:

    - 基本類型的值是其本身

    - 引用變量的值是一個(gè)地址值,是被引用對(duì)象的首地址

 3、為了避免引用參數(shù)傳遞的副作用, 建議一切結(jié)果使用返回值帶回。

如:

    /**
     * Java方法參數(shù)傳遞規(guī)則:基于值的傳遞,是變量值的復(fù)制
     *     為了避免引用方法參數(shù)傳遞的副作用,建議一切結(jié)果使用返回值返回
     * @author xcbeyond
     */
    public class ParamaterDemo {
        public static void main(String[] args) {
            Koo koo = new Koo();
            int a = 1;
            update(a);
            update(koo);
            System.out.println("a="+a+",koo.a="+koo.a);//a=1,koo.a=2
            
            int b = update2(a);
            int c = update2(koo);
            System.out.println("b="+b+",c="+c);//2,3
            
        }
        
        public static void update(int a ) {
            a++;
        }
        public static void update(Koo koo) {
            koo.a++;
        }
        
        public static int  update2(int a ) {
            a++;
            return a;
        }
        public static int update2(Koo koo) {
            koo.a++;
            return koo.a;
        }
    }
     
    class Koo {
        int a = 1;
    }

 

3、繼承:

    考慮到程序的實(shí)時(shí)擴(kuò)展(添加新的屬性、方法等操作),更好的進(jìn)行維護(hù),于是引入“繼承”這個(gè)概念。它是在原有類的基礎(chǔ)上添加或修改(重寫)新的屬性和方法。子類繼承了父類的所有方法和屬性。

    用來表達(dá)類型概念上具體化,Java繼承用extends 關(guān)鍵字。子類是父類的具體化,父類是子類的泛化(概念抽象化)

 1>、子類繼承父類的屬性和方法

 2>、構(gòu)造器不能繼承!

 3>、實(shí)例化子類,會(huì)遞歸分配所有父類的空間

 4>、子類默認(rèn)調(diào)用父類的無參數(shù)構(gòu)造器

繼承特點(diǎn):

  1>、子類繼承父類的屬性和方法

  2>、構(gòu)造器不能繼承

  3>、創(chuàng)建子類實(shí)例,會(huì)遞歸分配所有父類的空間

  4>、子類默認(rèn)調(diào)用父類的無參數(shù)構(gòu)造器

  5>、子類可以覆蓋(重寫)父類的方法,修改父類行為

  6>、JAVA只能單一繼承

繼承中的語法現(xiàn)象:

  1>, 父類可以引用子類的實(shí)例,父類的實(shí)現(xiàn)是多態(tài)的。

  2>, 子類可以覆蓋父類的方法,修改父類的行為。

     - 方法覆蓋:子類覆蓋了父類“相同方法簽名”的方法。

     - 方法的覆蓋是由方法動(dòng)態(tài)綁定實(shí)現(xiàn)的,就是java虛擬機(jī)運(yùn)行時(shí)候確定執(zhí)行那個(gè)方法,java最終執(zhí)行子類的方法。

關(guān)于繼承中的構(gòu)造器:

  1> 、子類遞歸調(diào)用父類構(gòu)造器。

  2> 、默認(rèn)調(diào)用父類無參數(shù)構(gòu)造器!

  3> 、如果父類沒有無參數(shù)構(gòu)造器,就必須在子類中明確指定調(diào)用父類的有參數(shù)構(gòu)造器!

  4> 、使用super()調(diào)用父類構(gòu)造器,必須寫在子類構(gòu)造器第一行。

  5> 、編程建議:所有的類都提供無參數(shù)構(gòu)造器!減少繼承時(shí)候的麻煩。


如:

 

    /**
     * 子類構(gòu)造器一定調(diào)用父類的構(gòu)造器!
     * @author xcbeyond
     *
     */
     
    public class ConstructorDemo {
        public static void main(String[] args) {
            Goo goo = new Goo();
            System.out.println(goo.a);//5
        }
    }
     
    class Foo extends Object {//任何類都繼承Object類(超類)
        int a = 1;
     
        public Foo(int a) {
            super();//Object類的構(gòu)造器
            this.a = a;
        }
        
        public void Foo() {//構(gòu)造方法沒有返回類型值,這里并不是構(gòu)造方法,而是一個(gè)一般的方法而已!
            
        }
    }
     
    //class Goo extends Foo{}  //錯(cuò) , 父類沒有無參數(shù)構(gòu)造器
    class Goo extends Foo{
        public Goo() {
            //System.out.println();//super()必須放在構(gòu)造器的第一行
            super(5);//明確調(diào)用父類由參數(shù)構(gòu)造器
        }
    }

 

對(duì)象的實(shí)例化過程

  1>、 檢查類是否加載,如果沒有加載就加載這個(gè)類

    - 如果有父類,要加載所有父類

    - 懶惰式加載,如果第一次用到就加載,只加載一次

    - 通過CLASSPATH指定的路徑尋找類文件

    - 加載以后是一個(gè)對(duì)象,類型是Class

  2>、在內(nèi)存堆中分配對(duì)象空間

      遞歸分配所以父類屬性空間,然后分別子類的空間,屬性默認(rèn)自動(dòng)初始化,自動(dòng)初始化為“0”值:null,0,false,\u0000

  3>、執(zhí)行屬性的賦值

  4>、遞歸調(diào)用父類構(gòu)造器。(默認(rèn)調(diào)用父類無參數(shù)構(gòu)造器!)

  5>、調(diào)用本類構(gòu)造器

 

訪問控制:

   訪問控制修飾詞:public  protected  default  private

    - 聲明屬性和方法盡可能私有,這樣才能做到盡可能封裝

    - 提供適當(dāng)?shù)膶傩栽L問方法,適當(dāng)?shù)拈_放屬性的訪問

    - 不建議使用非公有類。就是說所有類都應(yīng)該是公有的,并且一個(gè)源文件一個(gè)類

 

屬性是靜態(tài)綁定到變量類型。

    方法是動(dòng)態(tài)綁定,由最終對(duì)象的方法決定。

如:

    /**
     * 屬性是靜態(tài)綁定到變量類型
     * 方法是動(dòng)態(tài)綁定,有最終對(duì)象的方法決定
     * @author xcbeyond
     *
     */
    public class FiledAccessDemo {
        public static void main(String[] args) {
            Goo goo = new Goo();
            Foo foo = goo;
            
            System.out.println(goo.a+","+goo.getA());//2,2
            System.out.println(foo.a+","+foo.getA());//1,2
        }
     
    }
    class Foo {
        int a = 1;
        public int getA() {
            return a;
        }
    }
    class Goo extends Foo {
        int a = 2;
        public int getA() {
            return a;     //retrun super.a;
        }
    }