java基礎(chǔ)篇——面向?qū)ο?/font>
作者:xcbeyond
瘋狂源自夢想,技術(shù)成就輝煌!微信公眾號:《程序猿技術(shù)大咖》號主,專注后端開發(fā)多年,擁有豐富的研發(fā)經(jīng)驗,樂于技術(shù)輸出、分享,現(xiàn)階段從事微服務(wù)架構(gòu)項目的研發(fā)工作,涉及架構(gòu)設(shè)計、技術(shù)選型、業(yè)務(wù)研發(fā)等工作。對于Java、微服務(wù)、數(shù)據(jù)庫、Docker有深入了解,并有大量的調(diào)優(yōu)經(jīng)驗。
引言:
面向?qū)ο蟮乃枷胝荍ava學(xué)習(xí)的核心部分,要是沒有搞懂面向?qū)ο?,那么就稱不上學(xué)過Java,因此,搞懂面向?qū)ο笫侵陵P(guān)重要的。對于初學(xué)者而言,首次接觸面向?qū)ο髸r,總感覺怪怪的,不知道究竟在干什么(我剛開始接觸也是這種感覺,漸漸的就找到感覺了),這其實都是正?,F(xiàn)象的,不然怎么有人說他是很抽象的啊。面向?qū)ο?,簡單的理解就是把一切事物按照它自己本有存在的特征、屬性通過自然組織語言組織起來,然后再用編程語言來實現(xiàn)。例如:人(類)本該就分有性別(男、女)、年齡、姓名等屬性特征,然對于每一個而言,他們往往具體不同的這些屬性特征值,于是就從“人”(類)這個類別中具體出來了每個人,即:類的實例化得到了對象。就可以對象他們進行相應(yīng)的操作了。
面向?qū)ο?OO):
按照東西的特征和自然組織形式, 進行軟件開發(fā)過程的組織, 是一個開發(fā)過程的方法論。
學(xué)習(xí)面向?qū)ο?
- 學(xué)習(xí)如何用OO語法描述事物的特征和自然組織形式.
- 學(xué)習(xí)面向?qū)ο笏季S的前提是樸素的哲學(xué)邏輯.
如: 多態(tài), 抽象概念的具體實現(xiàn)是多態(tài)的,
如:美女是多態(tài)的!
一、類(Class):
它是一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu),是把一類相似或相關(guān)聯(lián)數(shù)據(jù)的相關(guān)操作封裝在一起的一個集合。
1、類是用來描述一個領(lǐng)域模型中的具體概念(名詞)的。
2、領(lǐng)域模型: 一個應(yīng)用軟件業(yè)務(wù)范疇, 也叫業(yè)務(wù)模型.
3、屬性: 描述具體概念(事物)的特征.
如:<圖書館管理系統(tǒng)>中的概念: 書 Book
書的特征: 書號, 書名, 編號, 作者, 價格...
Java中類的寫法(語法)如下:
修飾詞 class 類名{
修飾詞 類型 屬性;
修飾符 返回值類型 方法名 {
// 方法體(實現(xiàn)類的相關(guān)操作)
}
}
如:
public class Book{
int id;
String name;
String[] authors;
String isbn;
double price;
}
二、對象:
1、 對象是類的具體實例!
比 如,書Book這個類,它只是代表了一類,你卻不知道它到底是什么書,但你只知道它擁有哪些特點屬性,即書名、書號、作者、書價等(類屬性)信息,為了對書Book這個類具體化,就引出了“對象”的概念,因此,對象就是類的具體實例。如:《山楂樹之戀》是一本書,《和空姐同居的日子》是一本書,他們屬于Book類的兩個不同的對象。
對象的創(chuàng)建是通過“new”運算符進行實例化的,即:
Book book = new Book();//book:引用 new Book():對象
看到這里,你或許還是一頭霧水,請不必?fù)?dān)心,先暫時記住就行了,隨后你就會徹底明白了。new Book()它是真正的在內(nèi)存中(準(zhǔn)確的說是在“堆”內(nèi)存中)創(chuàng)建了一個Book類的對象,此時在“棧”中創(chuàng)建了一個Book類型(類也屬于一種數(shù)據(jù)類型,一種引用類型中的“類類型”)的引用變量book,最終將變量book的地址指向了new Book()創(chuàng)建的對象。<這里地址指向關(guān)系,是隱含存在的一種指針,可以這么理解,僅供理解而已。但java卻是不存在指針的哦!> 。關(guān)于“堆”、“棧”可以參考《java核心內(nèi)容——分配管理》了解。
引用:是指向具體對象的句柄,相當(dāng)于自然語言的代詞。
1> 代詞本身不是對象,代詞引用了一個具體對象。
2> 在特殊情況下引用(代詞)可能指空。
3> 經(jīng)常簡單的敘述事物時候,不嚴(yán)格區(qū)別引用與對象。
如:
Book book = new Book();//book:引用 new Book():對象
book.name = "月子";
book.authors = new String[]{"白云","黑土"};
book = null;//book引用null
4>引用是null時候,訪問屬性或方法時候會出現(xiàn): 空指針異常
如:
book = null;
System.out.println(book.name);//異常
2、構(gòu)造器(構(gòu)造方法):
在上面語句Book book = new Book()中,或許對用new Book()創(chuàng)建對象時,并不知道其真正的含義,其中Book()就是一個Book類的一個構(gòu)造器(特殊的方法),用它來對對象的屬性進行初始化。
構(gòu)造器的使用:
1>、聲明在類內(nèi)部, 方法名與類名一致的方法叫構(gòu)造方法, 構(gòu)造方法不能聲明返回值類型。
2>、構(gòu)造方法可以包含參數(shù), 參數(shù)一般是創(chuàng)建對象實例,必須依賴的條件(前提條件)。
如:
public Book(int id,String name,String isbn) {
this.id = id;
this.name = name;
this.isbn = isbn;
}
3>、構(gòu)造方法經(jīng)常會重載
方法重載:方法的重新書寫,即重載
- 方法名一樣
- 方法參數(shù)不一樣
默認(rèn)構(gòu)造器:
對于每一個類都會存在一個構(gòu)造器的,只是有些是使用的默認(rèn)構(gòu)造器而已,沒有顯式的顯示出來。
1>、如果類沒有聲明任何構(gòu)造器,Javac自動提供一個默認(rèn)構(gòu)造器, 無參數(shù)默認(rèn)構(gòu)造器。
2>、如果提供構(gòu)造器聲明, Javac將不再提供默認(rèn)構(gòu) 造器。
如:(這個程序只是為了說明默認(rèn)構(gòu)造器而已,沒有其他實際價值)
/**
* 默認(rèn)構(gòu)造器的演示
* @author xcbeyond
*
*/
public class ConstructorDemo {
public static void main(String[] args) {
Foo foo = new Foo();
//Goo goo = new Goo();//錯誤,沒有參數(shù)的構(gòu)造器
//System.out.println(foo.a+","+goo.a);
//A 、編譯錯誤 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òu)造器
this.a = a;
}
}
new運算: 創(chuàng)建對象實例,如: Book book = new Book();
1、根據(jù)類的屬性在堆中分配對象空間。
2、根據(jù)參數(shù)類型調(diào)用構(gòu)造器。
3、new運算返回對象的引用地址。
對象的創(chuàng)建過程:
1、根據(jù)類的屬性在堆中分配對象空間,并且自動初始化。
2、根據(jù)參數(shù)類型調(diào)用構(gòu)造器。
this:
最大的作用就是讓類中一個方法訪問該類的另一個方法或?qū)傩浴his可以代表任何對象。
- this 是對當(dāng)前對象的引用, 是當(dāng)前對象本身。
- 可以使用this明確的訪問當(dāng)前對象的屬性或者方法。
- this() 是調(diào)用本類的其他構(gòu)造器, 可以使用構(gòu)造器的重用, 簡化代碼的實現(xiàn).
- this() 必須寫在構(gòu)造器的第一行!
如:public Book(int id ,String name) {
//System.out.print(id);//錯 ,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ù)值得副本(復(fù)制品)傳入方法內(nèi),而參數(shù)本身不會受到任何影響。
1、基本類型就是其中值的復(fù)制, 引用類型是引用值(地址)的復(fù)制。
2、 變量的值:
- 基本類型的值是其本身
- 引用變量的值是一個地址值,是被引用對象的首地址
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、繼承:
考慮到程序的實時擴展(添加新的屬性、方法等操作),更好的進行維護,于是引入“繼承”這個概念。它是在原有類的基礎(chǔ)上添加或修改(重寫)新的屬性和方法。子類繼承了父類的所有方法和屬性。
用來表達類型概念上具體化,Java繼承用extends 關(guān)鍵字。子類是父類的具體化,父類是子類的泛化(概念抽象化)
1>、子類繼承父類的屬性和方法
2>、構(gòu)造器不能繼承!
3>、實例化子類,會遞歸分配所有父類的空間
4>、子類默認(rèn)調(diào)用父類的無參數(shù)構(gòu)造器
繼承特點:
1>、子類繼承父類的屬性和方法
2>、構(gòu)造器不能繼承
3>、創(chuàng)建子類實例,會遞歸分配所有父類的空間
4>、子類默認(rèn)調(diào)用父類的無參數(shù)構(gòu)造器
5>、子類可以覆蓋(重寫)父類的方法,修改父類行為
6>、JAVA只能單一繼承
繼承中的語法現(xiàn)象:
1>, 父類可以引用子類的實例,父類的實現(xiàn)是多態(tài)的。
2>, 子類可以覆蓋父類的方法,修改父類的行為。
- 方法覆蓋:子類覆蓋了父類“相同方法簽名”的方法。
- 方法的覆蓋是由方法動態(tài)綁定實現(xiàn)的,就是java虛擬機運行時候確定執(zhí)行那個方法,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)造器!減少繼承時候的麻煩。
如:
/**
* 子類構(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)造方法,而是一個一般的方法而已!
}
}
//class Goo extends Foo{} //錯 , 父類沒有無參數(shù)構(gòu)造器
class Goo extends Foo{
public Goo() {
//System.out.println();//super()必須放在構(gòu)造器的第一行
super(5);//明確調(diào)用父類由參數(shù)構(gòu)造器
}
}
對象的實例化過程
1>、 檢查類是否加載,如果沒有加載就加載這個類
- 如果有父類,要加載所有父類
- 懶惰式加載,如果第一次用到就加載,只加載一次
- 通過CLASSPATH指定的路徑尋找類文件
- 加載以后是一個對象,類型是Class
2>、在內(nèi)存堆中分配對象空間
遞歸分配所以父類屬性空間,然后分別子類的空間,屬性默認(rèn)自動初始化,自動初始化為“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)該是公有的,并且一個源文件一個類
屬性是靜態(tài)綁定到變量類型。
方法是動態(tài)綁定,由最終對象的方法決定。
如:
/**
* 屬性是靜態(tài)綁定到變量類型
* 方法是動態(tài)綁定,有最終對象的方法決定
* @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;
}
}