面向?qū)ο笫?Java 最重要的特性蜒滩。Java 是徹底的姑隅、純粹的面向?qū)ο笳Z(yǔ)言,在 Java 中“一切都是對(duì)象”衣式。本章將介紹面向?qū)ο蠡A(chǔ)知識(shí)。
面向?qū)ο?/p>
- 相對(duì)面向過程而言, 面向?qū)ο蠛兔嫦蜻^程都是一種思想
- 將功能封裝進(jìn)對(duì)象檐什,強(qiáng)調(diào)具備了功能的對(duì)象碴卧。
- 是一種符合人們思考習(xí)慣的思想, 可以將復(fù)雜的事情簡(jiǎn)單化, 將程序員從執(zhí)行者轉(zhuǎn)換成了指揮者.
面向?qū)ο蟮拈_發(fā)過程: 其實(shí)就是不斷的創(chuàng)建對(duì)象,使用對(duì)象乃正,指揮對(duì)象做事情住册。
面向?qū)ο蟮脑O(shè)計(jì)過程: 其實(shí)就是在管理和維護(hù)對(duì)象之間的關(guān)系。
面向?qū)ο蟮奶卣鳎?/p>
- 封裝(encapsulation): 封裝能夠使外部訪問者不能隨意存取對(duì)象的內(nèi)部數(shù)據(jù)烫葬,隱藏了對(duì)象的內(nèi)部細(xì)節(jié)界弧,只保留有限的對(duì)外接口凡蜻。外部訪問者不用關(guān)心對(duì)象的內(nèi)部細(xì)節(jié),使得操作對(duì)象變得簡(jiǎn)單垢箕。
- 繼承(inheritance)
- 多態(tài)(polymorphism): 指在父類中成員變量和成員方法被子類繼承之后划栓,可以具有不同的狀態(tài)或表現(xiàn)行為。
什么是類
Java中用類 Class 來描述事物.是具體事物的抽象条获,概念上的定義忠荞。
- 屬性:對(duì)應(yīng)類中的成員變量。
- 行為:對(duì)應(yīng)類中的成員函數(shù)帅掘。
類定義包括類聲明和類體兩部分,類定義的語(yǔ)法格式如下:
[public][abstract|final] class className [extends superclassName] [implements interfaceNameList] {類體}
對(duì)象的創(chuàng)建
創(chuàng)建對(duì)象及訪問對(duì)象成員
- 聲明對(duì)象與聲明普通變量沒有區(qū)別 委煤,格式為
type objectName;
聲明對(duì)象并不為對(duì)象分配內(nèi)存空間,而只是未存儲(chǔ)對(duì)象的地址分配內(nèi)存空間 - 實(shí)例化對(duì)象修档。分為兩個(gè)階段:為對(duì)象分配內(nèi)存空間和初始化對(duì)象碧绞,首先使用new運(yùn)算符為對(duì)象分配內(nèi)存空間,然后再調(diào)用構(gòu)造方法初始化對(duì)象吱窝。格式如下:
new 類的構(gòu)造方法();
- 通過引用變量訪問對(duì)象成員
- 引用變量名.屬性
- 引用變量名.方法名(實(shí)參表)
什么是方法
方法聲明
修飾符 1 修飾符2... 返回值類型 方法名(形參表) [ throws 異常列表 ] { }
其中返回值是方法在操作完成后返還調(diào)用它的環(huán)境的數(shù)據(jù),形式有2種:
- return 表達(dá)式; // 方法返回結(jié)果為表達(dá)式的值;
- return; // 用于無(wú)返回值的方法退出,無(wú)返回值末尾可不寫;
參數(shù)傳遞
- 基本數(shù)據(jù)類型的參數(shù)傳遞是以傳值的方式進(jìn)行讥邻,即將實(shí)際參數(shù)的值傳遞給形參; 在方法內(nèi)對(duì)形參的修改只影響形參單元,不影響實(shí)參
- 引用類型(如對(duì)象院峡、數(shù)組等)參數(shù)傳遞是按地址進(jìn)行傳遞的兴使。在方法內(nèi)對(duì)形參的訪問實(shí)際是訪問所指引用對(duì)象
方法的特點(diǎn):
將功能代碼進(jìn)行封裝,便于對(duì)該功能進(jìn)行調(diào)用。只有被調(diào)用才被執(zhí)行照激,提高了代碼的復(fù)用性. (注意不能在函數(shù)的內(nèi)部定義方法) 发魄。
方法的重載(Overload):
- 在同一個(gè)類中,允許存在一個(gè)以上的同名函數(shù)俩垃,函數(shù)參數(shù)個(gè)數(shù)或類型至少其一不同.
- 由于只考慮參數(shù)類型和個(gè)數(shù)的差異 ,不考慮出現(xiàn)返回值類型的差異. 因?yàn)檫@將導(dǎo)致算法的不確定性,這是不可能存在的励幼。強(qiáng)烈建議重載其返回值類型相同。
- 方法調(diào)用的匹配處理原則是口柳,首先按“精確匹配”原則去查找匹配方法赏淌,如果找不到,則按“自動(dòng)類型轉(zhuǎn)換匹配”原則去查找能匹配的方法啄清。
- 所謂“精確匹配”就是實(shí)參和形參類型完全一致
- 所謂“自動(dòng)轉(zhuǎn)換匹配”是指雖然實(shí)參和形參類型不同六水,但能將實(shí)參的數(shù)據(jù)按自動(dòng)轉(zhuǎn)換原則賦值給形參。
mybatis 的 SQL 操作方法簽名不支持重載辣卒。
方法的覆蓋(Override)
- 方法名掷贾、參數(shù)列表、完全相同才會(huì)產(chǎn)生方法覆蓋荣茫;
- 返回類型通常也要一致想帅,只有返回類型為引用類型時(shí),允許子類方法的返回類型是父類方法返回類型的子類型啡莉。
- 覆蓋不能改變方法的靜態(tài)與非靜態(tài)屬性港准。子類中不能將父類非靜態(tài)方法定義為靜態(tài)方法旨剥,反之也一樣。
- final 方法不能被覆蓋浅缸。
不允許子類方法的訪問修飾符比父類有更多的限制轨帜。例如:子類不能將父類的 public 方法定義為 protected 方法。但可以將父類的 private 方法在子類中重新定義為 public 方法.通常將子類方法訪問修飾符與父類保持一致.
構(gòu)造方法
作用: 給對(duì)象進(jìn)行初始化
構(gòu)造方法的特點(diǎn)
- 構(gòu)造方法的名稱必須與類名同名衩椒;
- 構(gòu)造方法沒有返回類型, 包括void, 所以不可以寫return語(yǔ)句;
- 構(gòu)造方法只能與 new 運(yùn)算符結(jié)合使用;
- 通常一個(gè)類可提供多個(gè)構(gòu)造方法蚌父,這些方法的參數(shù)不同。在創(chuàng)建對(duì)象
時(shí)毛萌,系統(tǒng)自動(dòng)調(diào)用參數(shù)匹配的構(gòu)造方法為對(duì)象初始化 - 如果一個(gè)類未指定構(gòu)造方法苟弛,則系統(tǒng)自動(dòng)提供的無(wú)參構(gòu)造方法,但如果自定義了構(gòu)造方法阁将,則系統(tǒng)不再提供無(wú)參構(gòu)造方法膏秫。
無(wú)參構(gòu)造方法形式如下: public Person() { } , 所以自己最好還要默默的加入無(wú)參構(gòu)造方法 - 什么時(shí)候定義構(gòu)造方法: 當(dāng)分析事物時(shí), 該事物具備一定特性或行為, 可以將這些內(nèi)容定義在構(gòu)造方法中.
一個(gè)類默認(rèn)有一個(gè)空參數(shù)的構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)的權(quán)限與所屬類一致. 如果類被 public 修飾,則默認(rèn)的構(gòu)造函數(shù)也被 public 修飾.總之默認(rèn)構(gòu)造函數(shù)的權(quán)限是隨著類而變化.
對(duì)象的初始化和構(gòu)造方法
在創(chuàng)建對(duì)象時(shí),要給對(duì)象的屬性成員分配內(nèi)存空間做盅,同時(shí)進(jìn)行初始化荔睹。
- 如果定義屬性成員時(shí)沒有指定初值,則系統(tǒng)自動(dòng)指定初值.在定義屬性成員時(shí)也可以指定初值.public class Point { private int x=10; ……
- 指定初值的另一種辦法是通過初始化塊來設(shè)置對(duì)象的初值(也叫做構(gòu)造代碼塊,它是給所有對(duì)象進(jìn)行統(tǒng)一初始化)言蛇。
// 注意首先是按照屬性定義的初值,然后是初始化塊, - 最后是構(gòu)造方法:構(gòu)造方法是給對(duì)相關(guān)設(shè)置初值的規(guī)范方法,構(gòu)造方法是根據(jù)方法參數(shù)給對(duì)象屬性賦不同的值
成員變量
聲明類體中成員變量語(yǔ)法格式如下:
[public | protected | private ] [static] [final] type variableName; //成員變量
成員方法
[public | protected | private ] [static] [final | abstract] [native] [synchronized] type methodName([paramList]) [throws exceptionList] { //方法體 }
static關(guān)鍵字
靜態(tài)屬性
用 static 修飾的屬性是屬于類的靜態(tài)屬性, 相應(yīng)的成員變量為類變量
- 類變量的訪問形式
- 在本類中直接訪問:count
- 通過類名訪問:User.count
- 不建議通過類的一個(gè)對(duì)象訪問,如:x1.count, 實(shí)際上還是通過類名的方式訪問
- 給類變量賦初值
默認(rèn)賦值即可,也可以用靜態(tài)初始化代碼塊 static{count=100;}
// 靜態(tài)初始化代碼的執(zhí)行是在main方法執(zhí)行前完成宵距。 - 被 static 修飾的類成員特點(diǎn):是共享數(shù)據(jù), 隨著類的加載而加載, 優(yōu)先于對(duì)象存在, 被所有對(duì)象所共享, 可以直接被類名調(diào)用.
靜態(tài)方法
用 static 修飾的方法稱為靜態(tài)方法腊尚,也叫類方法. 在 static 方法中只能處理類變量,也可訪問其它 static 方法满哪,但不能訪問任何歸屬對(duì)象空間的變量或方法.
而非靜態(tài)成員變量和方法卻可以訪問靜態(tài)資源.
- 靜態(tài)方法中不可以寫 this婿斥,super 關(guān)鍵字
- 主函數(shù)是靜態(tài)方法.
tip: 創(chuàng)建某個(gè)工具類, 可只提供相應(yīng)的靜態(tài)方法, 進(jìn)一步為了讓某個(gè)類不能創(chuàng)建對(duì)象, 可以私有化構(gòu)造函數(shù).
理解 this 和 super
出現(xiàn)在類的實(shí)例方法或構(gòu)造方法中,this 代表所在函數(shù)所屬對(duì)象的引用哨鸭。用 this 作前綴可訪問當(dāng)前對(duì)象的實(shí)例變量或成員方法.
- this.實(shí)例變量; // 能加 this 則盡量加, 這樣代碼更清晰
- this.成員方法; // 本類成員方法的調(diào)用, 能加 this 則盡量加 this
- this(參數(shù)),用來調(diào)用同類其他構(gòu)造方法.注意 this 語(yǔ)句只能定義在構(gòu)造函數(shù)的第一行,因?yàn)槌跏蓟葓?zhí)行.
super關(guān)鍵字則和 this 差不多,都是一個(gè)引用指向自身和上一級(jí)父類罷了.
this()構(gòu)造的此類用法, 可以減少構(gòu)造的一些重復(fù)代碼
public Msg() {
this(0, null, -1);
}
public Msg(int no) {
this(no, null);
}
public Msg(int no, String str) {
this(no, str);
}
對(duì)象初始化過程總結(jié)
- new 用到了class 文件, 所以先會(huì)找到 class文件并加載到內(nèi)存
- 執(zhí)行類的static {}代碼塊
- 在堆內(nèi)存中開辟空間,分配內(nèi)存地址
- 在堆內(nèi)存中建立對(duì)象的特有屬性, 并默認(rèn)初始化
- 對(duì)屬性顯示初始化;
- 構(gòu)造代碼塊初始化{};
- 構(gòu)造函數(shù)初始化;
- 將內(nèi)存地址賦給棧內(nèi)存變量.
所以加載順序中: 屬性顯示初始化 早于
構(gòu)造代碼塊初始化 早于
構(gòu)造函數(shù)初始化
與之類似, 靜態(tài)屬性顯示初始化 早于
靜態(tài)構(gòu)造代碼塊初始化
代碼的組織形式-使用包
在 Java 中為了防止類民宿、接口、枚舉和注釋等命名沖突引用了包(package)概念像鸡,包本質(zhì)上命名空間(namespace)活鹰。在包中可以定義一組相關(guān)的類型(類、接口只估、枚舉和注釋)志群,并為它們提供訪問保護(hù)和命名空間管理。
package 語(yǔ)句定義包蛔钙,package 語(yǔ)句應(yīng)該放在源文件的第一行锌云,在每個(gè)源文件中只能有一個(gè)包定義語(yǔ)句,并且 package 語(yǔ)句適用于所有類型(類吁脱、接口桑涎、枚舉和注釋)的文件彬向。定義包語(yǔ)法格式如下:package pkg1[.pkg2[.pkg3…]];
Java API簡(jiǎn)介: Java 中按包來組織類.包的組織采用分層結(jié)構(gòu),與文件系統(tǒng)中的目錄的組織對(duì)應(yīng)一致.通常將邏輯相關(guān)的類放在同一個(gè)包中。
包將類的命名空間進(jìn)行有效劃分,同一包中不能有兩個(gè)同名的類. Java 系統(tǒng)提供的類庫(kù)也成為Java API, 是系統(tǒng)提供的已實(shí)現(xiàn)的標(biāo)準(zhǔn)類的集合攻冷。
建立包
創(chuàng)建包就是在指定目錄路徑下創(chuàng)建一個(gè)子文件夾娃胆,這個(gè)包中所有類的字節(jié)碼文件將存放在該文件夾下。
方法1: 創(chuàng)建一個(gè) test 子目錄讲衫,將源程序文件存放到該目錄缕棵,在該目錄下利用javac編譯源代碼,或者在別處編譯完程序后將字節(jié)碼文件拷貝到該目錄即可涉兽。
方法2: 采用帶路徑指示的編譯命令: 格式:javac –d destpath Point.java
編譯器將自動(dòng)在 destpath 指定的目錄下建一個(gè)test子目錄招驴,并將產(chǎn)生的字節(jié)碼文件保存到該子目錄下 。典型用法是源程序放在當(dāng)前目錄下, 用如下命令編譯 javac –d . Point.java
枷畏。編譯后將在當(dāng)前目錄自動(dòng)創(chuàng)建 test 子目錄
包的引用
同一個(gè)包下的類之間互相引用是不需要包名的别厘,可以直接使用。但如果類不在同一個(gè)包內(nèi)拥诡,則必須要知道其所在的包触趴。
- 使用類的完全限定名 :new java.util.Date()
- 用 import 語(yǔ)句加載需要使用的類。例: import java.util.Date; 然后在程序中可以直接通過類名創(chuàng)建對(duì)象, 如:new Date(); 用 import 語(yǔ)句加載整個(gè)包, 用
*
號(hào)代替類名位置渴肉。 它將加載包中的所有的類冗懦。例:import java.util.*;
- 使用靜態(tài)導(dǎo)入,它有一個(gè) static 關(guān)鍵字仇祭,可以直接導(dǎo)入類的公開靜態(tài)方法和成員披蕉。例:
import static java.util.Arrays.*;
。但是注意靜態(tài)導(dǎo)入不應(yīng)過度使用乌奇,否則難以區(qū)分訪問的是哪個(gè)類的代碼没讲。
封裝性與訪問控制
Java 面向?qū)ο蟮姆庋b性是通過對(duì)成員變量和方法進(jìn)行訪問控制實(shí)現(xiàn)的,訪問控制分為4個(gè)等級(jí):私有礁苗、默認(rèn)爬凑、保護(hù)和公有
- 公有級(jí)別的關(guān)鍵字是 public,公有級(jí)別的成員變量和方法可以在任何場(chǎng)合被直接訪問试伙,是最寬松的一種訪問控制等級(jí)嘁信。
- 保護(hù)級(jí)別的關(guān)鍵字是 protected,保護(hù)級(jí)別在同一包中完全與默認(rèn)訪問級(jí)別一樣疏叨,但是不同包中子類能夠繼承父類中的 protected 變量和方法吱抚,這就是所謂的保護(hù)級(jí)別,“保護(hù)”就是保護(hù)某個(gè)類的子類都能繼承該類的變量和方法秘豹。
- 默認(rèn)級(jí)別沒有關(guān)鍵字,也就是沒有訪問修飾符昌粤,默認(rèn)級(jí)別的成員變量和方法既绕,可以在其所在類內(nèi)部和同一個(gè)包的其他類中被直接訪問啄刹,但在不同包的類中則不允許直接訪問。
- 私有級(jí)別的關(guān)鍵字是 private凄贩,私有級(jí)別的成員變量和方法只能在其所在類的內(nèi)部自由使用誓军,在其他的類中則不允許直接訪問。
提示 訪問類成員時(shí)疲扎,在能滿足使用的前提下昵时,應(yīng)盡量限制類中成員的可見性,訪問級(jí)別順序是:私有級(jí)別→默認(rèn)級(jí)別→保護(hù)級(jí)別→公有級(jí)別椒丧。
Jar 包
為方便使用第三方代碼壹甥,也為了方便我們寫的代碼給其他人使用,各種程序語(yǔ)言大多有打包的概念壶熏,打包的一般不是源代碼句柠,而是編譯后的代碼。打包將多個(gè)編譯后的文件打包為一個(gè)文件棒假,方便其他程序調(diào)用溯职。
在Java中,編譯后的一個(gè)或多個(gè)包的Java class文件可以打包為一個(gè)文件帽哑,Java中打包命令為jar谜酒,打包后的文件擴(kuò)展名為.jar,一般稱之為jar包妻枕。
可以使用如下方式打包僻族,首先到編譯后的java class文件根目錄,然后運(yùn)行如下命令:
jar -cvf hello.jar <最上層包名>
程序的編譯與鏈接
從Java 源代碼到運(yùn)行的程序佳头,有編譯和鏈接兩個(gè)步驟。編譯是將源代碼文件變成擴(kuò)展名是.class的一種字節(jié)碼晴氨,這個(gè)工作一般是由 javac 命令完成的康嘉。鏈接是在運(yùn)行時(shí)動(dòng)態(tài)執(zhí)行的,.class 文件不能直接運(yùn)行籽前,運(yùn)行的是Java虛擬機(jī)亭珍,虛擬機(jī)聽起來比較抽象,執(zhí)行的就是 Java 命令枝哄,這個(gè)命令解析 .class文件肄梨,轉(zhuǎn)換為機(jī)器能識(shí)別的二進(jìn)制代碼,然后運(yùn)行挠锥。所謂鏈接就是根據(jù)引用到的類加載相應(yīng)的字節(jié)碼并執(zhí)行众羡。
Java編譯和運(yùn)行時(shí),都需要以參數(shù)指定一個(gè)classpath蓖租,即類路徑粱侣。類路徑可以有多個(gè)羊壹,對(duì)于直接的class文件,路徑是class文件的根目錄齐婴;對(duì)于jar包油猫,路徑是jar包的完整名稱(包括路徑和jar包名)。
總結(jié)來說柠偶,import 是編譯時(shí)概念情妖,用于確定完全限定名,在運(yùn)行時(shí)诱担,只根據(jù)完全限定名尋找并加載類毡证,編譯和運(yùn)行時(shí)都依賴類路徑,類路徑中的 jar 文件會(huì)被解壓縮用于尋找和加載類该肴。
對(duì)象銷毀
對(duì)象不再使用時(shí)應(yīng)該銷毀情竹。C++ 語(yǔ)言對(duì)象是通過 delete 語(yǔ)句手動(dòng)釋放,Java語(yǔ)言對(duì)象是由垃圾回收器(Garbage Collection)收集然后釋放匀哄,程序員不用關(guān)心釋放的細(xì)節(jié)秦效。自動(dòng)內(nèi)存管理是現(xiàn)代計(jì)算機(jī)語(yǔ)言發(fā)展趨勢(shì),例如:C# 語(yǔ)言的垃圾回收涎嚼,Objective-C 和 Swift 語(yǔ)言的 ARC(內(nèi)存自動(dòng)引用計(jì)數(shù)管理)阱州。
垃圾回收器(Garbage Collection)的工作原理是:當(dāng)一個(gè)對(duì)象的引用不存在時(shí),認(rèn)為該對(duì)象不再需要法梯,垃圾回收器自動(dòng)掃描對(duì)象的動(dòng)態(tài)內(nèi)存區(qū)苔货,把沒有引用的對(duì)象作為垃圾收集起來并釋放。