面向?qū)ο?/h1>
什么是面向?qū)ο螅?/h2>
面向?qū)ο?Object-Oriented舞丛,簡稱OO)是一種編程方法,它將數(shù)據(jù)和對數(shù)據(jù)的操作封裝在一個對象中果漾,使得程序更易理解瓷马、修改和擴展。面向?qū)ο笏枷胝J(rèn)為跨晴,計算機程序應(yīng)該被視為一組對象的集合欧聘,每個對象都應(yīng)該能夠接收其他對象發(fā)來的消息,并能根據(jù)這些消息執(zhí)行相應(yīng)的動作端盆。
在面向?qū)ο缶幊讨谢持瑁瑢ο笫且粋€具有特定屬性和方法的實體费封。屬性描述對象的狀態(tài),方法則用來操作這些狀態(tài)蒋伦。對象可以看做是現(xiàn)實世界中的事物弓摘,具有自己的屬性和行為,這種設(shè)計方式符合人們對事物的認(rèn)知方式痕届。
通過面向?qū)ο缶幊倘拖祝覀兛梢詣?chuàng)建抽象的數(shù)據(jù)類型,并定義其屬性和方法研叫。這樣做可以隱藏數(shù)據(jù)的具體實現(xiàn)細(xì)節(jié)锤窑,從而使得程序更加模塊化,降低了耦合度嚷炉,提高了代碼的可維護(hù)性和可重用性渊啰。
常見的面向?qū)ο缶幊陶Z言包括Java、C++申屹、Python等绘证,這些語言可以很好地支持面向?qū)ο缶幊谭妒剑ㄟ^類和對象的概念來管理數(shù)據(jù)和操作哗讥。
面向?qū)ο髢?yōu)點
- 將復(fù)雜的問題簡單化
- 更貼合與生活中人們的思維角度
- 面向過程更適合執(zhí)行者的思考方式,面向?qū)ο筮m合于管理者的思考方式
面向?qū)ο笈c面向過程
面向?qū)ο?Object-Oriented嚷那,簡稱OO)和面向過程(Procedural-oriented,簡稱PO)是兩種不同的編程范式杆煞。
在面向過程編程中车酣,程序被看做是一系列可執(zhí)行的步驟,這些步驟依次被執(zhí)行索绪,流程式地推進(jìn)湖员。程序主要由函數(shù)、數(shù)據(jù)結(jié)構(gòu)等組成瑞驱,函數(shù)對數(shù)據(jù)進(jìn)行操作娘摔。在面向過程編程中,重點是函數(shù)的設(shè)計和實現(xiàn)唤反,數(shù)據(jù)則是通過參數(shù)傳遞給函數(shù)凳寺。
而在面向?qū)ο缶幊讨校绦虮辉O(shè)計為一組相互關(guān)聯(lián)的對象集合彤侍,每個對象都具有特定的屬性和行為肠缨,并且能夠與其他對象進(jìn)行通信。程序主要由類及其實例對象組成盏阶,類描述了對象的屬性和行為晒奕,實例對象則是類的具體化。在面向?qū)ο缶幊讨校攸c是對象的設(shè)計和建模脑慧,通過使用繼承魄眉、封裝和多態(tài)等機制來組織程序邏輯。
因此闷袒,面向過程和面向?qū)ο蟮闹饕獏^(qū)別在于思想方式和實現(xiàn)方法坑律。面向過程重視步驟和函數(shù),通過分解問題并設(shè)計函數(shù)來解決問題囊骤;面向?qū)ο髣t更注重對象和類之間的關(guān)系晃择,將程序中的各種元素組織成一個有機整體,在實現(xiàn)上更加靈活和可擴展也物。同時宫屠,面向?qū)ο蟮某绦蚓哂懈叩膹?fù)用性、可維護(hù)性和可讀性焦除。
當(dāng)然,這兩種編程方式都有其優(yōu)缺點作彤,具體應(yīng)該根據(jù)問題的實際情況來選擇合適的編程方式膘魄。
總結(jié):
- 都是一種思想,思維方式,思考問題的角度
- 面相過程 : 關(guān)注"我該如何實現(xiàn)",然后一步一步實現(xiàn)
- 面相對象 : 關(guān)注"我該找誰實現(xiàn)",不關(guān)注實現(xiàn)步驟,只關(guān)注這個"誰",'誰'就是對象
如何通過面向?qū)ο笏枷脒M(jìn)行編程
將程序與現(xiàn)實生活緊密聯(lián)系
對象|實例 : 描述現(xiàn)實生活中的真實存在的事物
類 : 定義一系列對象的共性-->圖紙|模版|實體類
先有類,再根據(jù)類創(chuàng)建對象
類與對象的概念
在面向?qū)ο蟮木幊讨校惡蛯ο笫莾蓚€重要的概念竭讳。
類(Class)是一種抽象的數(shù)據(jù)類型创葡,它描述了一組具有相同屬性和方法的對象集合。類可以看做是一種模板或者藍(lán)圖绢慢,它定義了一組數(shù)據(jù)結(jié)構(gòu)和操作這些數(shù)據(jù)的方法灿渴。
對象(Object)是類的一個實例,它具有類定義的屬性和行為胰舆。在面向?qū)ο缶幊讨猩叮覀兺ㄟ^創(chuàng)建對象來使用類中定義的方法和屬性。
類與對象的關(guān)系
- 類定義了一組屬性和方法缚窿,對象包含了這些屬性值和方法實現(xiàn)棘幸。
- 對象通過類來創(chuàng)建,一個類可以創(chuàng)建多個對象倦零。
- 在改變一個對象的屬性值或調(diào)用一個對象的方法時误续,不會影響其他對象或類本身。
類與對象的區(qū)別
-
抽象程度不同
類是一種抽象的數(shù)據(jù)結(jié)構(gòu)扫茅,它描述了一組對象的共同特征蹋嵌,包括屬性和方法等。而對象則是類的具體化葫隙,它包含了類定義的屬性值和方法實現(xiàn)栽烂,是具體的實體。
-
內(nèi)容不同
類包含了屬性和方法的定義,但沒有具體的值或?qū)崿F(xiàn)愕鼓。而對象則是具有這些屬性值和方法實現(xiàn)的實體钙态,是一個具體的實例。
-
使用方式不同
類是一種模板或者藍(lán)圖菇晃,它用于創(chuàng)建對象册倒、描述對象的屬性和行為等,是對實現(xiàn)進(jìn)行了封裝和抽象的結(jié)果磺送。而對象則是類的具體實現(xiàn)驻子,通過對象可以直接訪問類中定義的屬性和方法。
-
存儲位置不同
類通常在代碼中被定義估灿,是靜態(tài)的崇呵,存儲于磁盤上;而對象則是在程序運行時創(chuàng)建的馅袁,存儲于內(nèi)存中域慷。
-
可變性不同
類是一種不可變的數(shù)據(jù)結(jié)構(gòu),它定義了一組屬性和方法汗销,但不能直接改變這些屬性和方法的定義犹褒。而對象則是可變的,可以修改它們的屬性值或?qū)崿F(xiàn)方法弛针。
綜上所述叠骑,類是一種描述共同特征的抽象數(shù)據(jù)類型,而對象是類的一個具體實例削茁,包含了類定義的屬性值和方法實現(xiàn)宙枷。類和對象之間的關(guān)系是類定義了對象的共同特征,而對象實現(xiàn)了這些特征茧跋。兩者的使用方式慰丛、存儲位置、可變性等方面也有所不同瘾杭。
自定義類與對象
自定義類
定義類(類的組成)
屬性 field
方法 method
構(gòu)造方法 constructor
其他:代碼塊 靜態(tài)代碼塊 內(nèi)部類
屬性(field 成員變量)
屬性用于定義該類或該類對象包含的數(shù)據(jù)或者說靜態(tài)特征璧帝。
屬性作用范圍是整個類體。
在定義成員變量時可以對其初始化富寿,如果不對其初始化睬隶,Java使用默認(rèn)的值對其初始化
面向?qū)ο?Object-Oriented舞丛,簡稱OO)是一種編程方法,它將數(shù)據(jù)和對數(shù)據(jù)的操作封裝在一個對象中果漾,使得程序更易理解瓷马、修改和擴展。面向?qū)ο笏枷胝J(rèn)為跨晴,計算機程序應(yīng)該被視為一組對象的集合欧聘,每個對象都應(yīng)該能夠接收其他對象發(fā)來的消息,并能根據(jù)這些消息執(zhí)行相應(yīng)的動作端盆。
在面向?qū)ο缶幊讨谢持瑁瑢ο笫且粋€具有特定屬性和方法的實體费封。屬性描述對象的狀態(tài),方法則用來操作這些狀態(tài)蒋伦。對象可以看做是現(xiàn)實世界中的事物弓摘,具有自己的屬性和行為,這種設(shè)計方式符合人們對事物的認(rèn)知方式痕届。
通過面向?qū)ο缶幊倘拖祝覀兛梢詣?chuàng)建抽象的數(shù)據(jù)類型,并定義其屬性和方法研叫。這樣做可以隱藏數(shù)據(jù)的具體實現(xiàn)細(xì)節(jié)锤窑,從而使得程序更加模塊化,降低了耦合度嚷炉,提高了代碼的可維護(hù)性和可重用性渊啰。
常見的面向?qū)ο缶幊陶Z言包括Java、C++申屹、Python等绘证,這些語言可以很好地支持面向?qū)ο缶幊谭妒剑ㄟ^類和對象的概念來管理數(shù)據(jù)和操作哗讥。
面向?qū)ο髢?yōu)點
- 將復(fù)雜的問題簡單化
- 更貼合與生活中人們的思維角度
- 面向過程更適合執(zhí)行者的思考方式,面向?qū)ο筮m合于管理者的思考方式
面向?qū)ο笈c面向過程
面向?qū)ο?Object-Oriented嚷那,簡稱OO)和面向過程(Procedural-oriented,簡稱PO)是兩種不同的編程范式杆煞。
在面向過程編程中车酣,程序被看做是一系列可執(zhí)行的步驟,這些步驟依次被執(zhí)行索绪,流程式地推進(jìn)湖员。程序主要由函數(shù)、數(shù)據(jù)結(jié)構(gòu)等組成瑞驱,函數(shù)對數(shù)據(jù)進(jìn)行操作娘摔。在面向過程編程中,重點是函數(shù)的設(shè)計和實現(xiàn)唤反,數(shù)據(jù)則是通過參數(shù)傳遞給函數(shù)凳寺。
而在面向?qū)ο缶幊讨校绦虮辉O(shè)計為一組相互關(guān)聯(lián)的對象集合彤侍,每個對象都具有特定的屬性和行為肠缨,并且能夠與其他對象進(jìn)行通信。程序主要由類及其實例對象組成盏阶,類描述了對象的屬性和行為晒奕,實例對象則是類的具體化。在面向?qū)ο缶幊讨校攸c是對象的設(shè)計和建模脑慧,通過使用繼承魄眉、封裝和多態(tài)等機制來組織程序邏輯。
因此闷袒,面向過程和面向?qū)ο蟮闹饕獏^(qū)別在于思想方式和實現(xiàn)方法坑律。面向過程重視步驟和函數(shù),通過分解問題并設(shè)計函數(shù)來解決問題囊骤;面向?qū)ο髣t更注重對象和類之間的關(guān)系晃择,將程序中的各種元素組織成一個有機整體,在實現(xiàn)上更加靈活和可擴展也物。同時宫屠,面向?qū)ο蟮某绦蚓哂懈叩膹?fù)用性、可維護(hù)性和可讀性焦除。
當(dāng)然,這兩種編程方式都有其優(yōu)缺點作彤,具體應(yīng)該根據(jù)問題的實際情況來選擇合適的編程方式膘魄。
總結(jié):
- 都是一種思想,思維方式,思考問題的角度
- 面相過程 : 關(guān)注"我該如何實現(xiàn)",然后一步一步實現(xiàn)
- 面相對象 : 關(guān)注"我該找誰實現(xiàn)",不關(guān)注實現(xiàn)步驟,只關(guān)注這個"誰",'誰'就是對象
如何通過面向?qū)ο笏枷脒M(jìn)行編程
將程序與現(xiàn)實生活緊密聯(lián)系
對象|實例 : 描述現(xiàn)實生活中的真實存在的事物
類 : 定義一系列對象的共性-->圖紙|模版|實體類
先有類,再根據(jù)類創(chuàng)建對象
類與對象的概念
在面向?qū)ο蟮木幊讨校惡蛯ο笫莾蓚€重要的概念竭讳。
類(Class)是一種抽象的數(shù)據(jù)類型创葡,它描述了一組具有相同屬性和方法的對象集合。類可以看做是一種模板或者藍(lán)圖绢慢,它定義了一組數(shù)據(jù)結(jié)構(gòu)和操作這些數(shù)據(jù)的方法灿渴。
對象(Object)是類的一個實例,它具有類定義的屬性和行為胰舆。在面向?qū)ο缶幊讨猩叮覀兺ㄟ^創(chuàng)建對象來使用類中定義的方法和屬性。
類與對象的關(guān)系
- 類定義了一組屬性和方法缚窿,對象包含了這些屬性值和方法實現(xiàn)棘幸。
- 對象通過類來創(chuàng)建,一個類可以創(chuàng)建多個對象倦零。
- 在改變一個對象的屬性值或調(diào)用一個對象的方法時误续,不會影響其他對象或類本身。
類與對象的區(qū)別
抽象程度不同
類是一種抽象的數(shù)據(jù)結(jié)構(gòu)扫茅,它描述了一組對象的共同特征蹋嵌,包括屬性和方法等。而對象則是類的具體化葫隙,它包含了類定義的屬性值和方法實現(xiàn)栽烂,是具體的實體。
內(nèi)容不同
類包含了屬性和方法的定義,但沒有具體的值或?qū)崿F(xiàn)愕鼓。而對象則是具有這些屬性值和方法實現(xiàn)的實體钙态,是一個具體的實例。
使用方式不同
類是一種模板或者藍(lán)圖菇晃,它用于創(chuàng)建對象册倒、描述對象的屬性和行為等,是對實現(xiàn)進(jìn)行了封裝和抽象的結(jié)果磺送。而對象則是類的具體實現(xiàn)驻子,通過對象可以直接訪問類中定義的屬性和方法。
存儲位置不同
類通常在代碼中被定義估灿,是靜態(tài)的崇呵,存儲于磁盤上;而對象則是在程序運行時創(chuàng)建的馅袁,存儲于內(nèi)存中域慷。
可變性不同
類是一種不可變的數(shù)據(jù)結(jié)構(gòu),它定義了一組屬性和方法汗销,但不能直接改變這些屬性和方法的定義犹褒。而對象則是可變的,可以修改它們的屬性值或?qū)崿F(xiàn)方法弛针。
綜上所述叠骑,類是一種描述共同特征的抽象數(shù)據(jù)類型,而對象是類的一個具體實例削茁,包含了類定義的屬性值和方法實現(xiàn)宙枷。類和對象之間的關(guān)系是類定義了對象的共同特征,而對象實現(xiàn)了這些特征茧跋。兩者的使用方式慰丛、存儲位置、可變性等方面也有所不同瘾杭。
自定義類與對象
自定義類
定義類(類的組成)
屬性 field
方法 method
構(gòu)造方法 constructor
其他:代碼塊 靜態(tài)代碼塊 內(nèi)部類
屬性(field 成員變量)
屬性用于定義該類或該類對象包含的數(shù)據(jù)或者說靜態(tài)特征璧帝。
屬性作用范圍是整個類體。
在定義成員變量時可以對其初始化富寿,如果不對其初始化睬隶,Java使用默認(rèn)的值對其初始化
數(shù)據(jù)類型 | 默認(rèn)值 |
---|---|
整型 | 0 |
浮點型 | 0.0 |
字符型 | '\u0000' |
布爾型 | false |
所有引用類型 | null |
屬性定義格式:
[修飾符] 屬性類型 屬性名 = [默認(rèn)值] ;
public class Person{
String name = "張三";
}
功能(方法)
方法用于定義該類或該類實例的行為特征和功能實現(xiàn)。方法是類和對象行為特征的抽象页徐。方法很類似于
面向過程中的函數(shù)苏潜。面向過程中,函數(shù)是最基本單位变勇,整個程序由一個個函數(shù)調(diào)用組成恤左。面向?qū)ο笾校?br> 整個程序的基本單位是類贴唇,方法是從屬于類和對象的。
方法定義格式:
[修飾符] 方法返回值類型 方法名(形參列表) {
// n條語句
}
public class Person{
//成員變量
String name;
//成員方法
public void study(){
System.out.println("一個程序猿正在努力工作...");
}
}
注意:
java是值傳遞 :
基本數(shù)據(jù)類型 : 數(shù)據(jù)值
引用數(shù)據(jù)類型 : 對象的地址值
方法的形參類型可以為任意數(shù)據(jù)類型,包含自定義的引用數(shù)據(jù)類型
方法的返回值類型可以為任意數(shù)據(jù)類型,包含自定義的引用數(shù)據(jù)類型
實例化對象
創(chuàng)建對象 : new創(chuàng)建對象
new創(chuàng)建對象步驟
- 在堆內(nèi)存中為對象開辟空間,成員變量跟隨對象進(jìn)入堆內(nèi)存,并附默認(rèn)值
- 調(diào)用構(gòu)造器為對象初始化想信息
- 將地址返回給引用
類名 對象名 = new 類名();
引用數(shù)據(jù)類型 對象名|引用名|變量名 = new 引用數(shù)據(jù)類型();
Person p1=new Person();
調(diào)用類的屬性和方法
對象名.成員變量 | 引用.屬性名
對象名.成員方法 | 引用.功能名字(實參)
p1.name = "李四";
p1.study();
類的實例
一般類中有三種常見的成員:屬性field飞袋、方法method戳气、構(gòu)造器constructor。這三種成員都可以定義零個或多個巧鸭。
編寫簡單的學(xué)生類:
public class Student {
//屬性(成員變量)
int id;
String sname;
int age;
//構(gòu)造方法
Student(){
}
//方法
void study(){
System.out.println("我正在學(xué)習(xí)瓶您!");
}
}
成員變量與局部變量的區(qū)別
聲明位置不同:
成員變量 :
類中方法外局部變量 :
方法中(塊中)
作用范圍不同:
成員變量 :
當(dāng)前類中局部變量 :
當(dāng)前方法不同的方法中即使有同名的局部變量,沒有關(guān)系纲仍,互不影響呀袱,建議相同
內(nèi)存存放的位置的:
成員變量 :
堆內(nèi)存中局部變量 :
棧內(nèi)存中
默認(rèn)值情況不同:
成員變量 :
有默認(rèn)值局部變量 :
沒有默認(rèn)值
class MyClass { // 實例變量的作用域
// 實例變量的聲明
public void aMethod(方法形參) { // 形參的作用域
// 局部變量的作用域
// 局部變量聲明
}
}
類與類之間的關(guān)系
類之間大體分為6種關(guān)系:在設(shè)計模式中類與類之間的關(guān)系主要有6種:依賴、關(guān)聯(lián)郑叠、聚合夜赵、組合、繼承乡革,實現(xiàn)寇僧, 它們之間的耦合
度依次增加。
繼承關(guān)系(Inheritance)
繼承指的是一個類(稱為子類沸版、子接口)繼承另外的一個類(稱為父類嘁傀、父接口)的功能,并可以增加
它自己的新功能的能力推穷。在Java中繼承關(guān)系通過關(guān)鍵字extends明確標(biāo)識心包。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZdMVqkFM-1681228352165)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681111495686.png)]
public class Person {
String name;
int age;
void eat(){}
void say(){}
}
//繼承
class Student extends Person{
void study(){}
}
class Teacher extends Person{
void teach(){}
}
實現(xiàn)關(guān)系
實現(xiàn)指的是一個class類實現(xiàn)interface接口(可以是多個)的功能类咧,實現(xiàn)是類與接口之間最常見的關(guān)系馒铃。
在Java中此類關(guān)系通過關(guān)鍵字implements明確標(biāo)識。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZLZFTCck-1681228352166)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681114862227.png)]
interface Vehicle{
void move();
}
class Ship implements Vehicle{
void move(){
System.out.println("水里移動..");
}
}
class Car implements Vehicle{
void move(){
System.out.println("陸地跑..");
}
}
依賴關(guān)系(Dependency)
依賴就是一個類A使用到了另一個類B痕惋,而這種使用關(guān)系是具有偶然性的区宇、臨時性的、非
常弱的值戳,但是類B的變化會影響到類A议谷。比如某人要過河,需要借用一條船堕虹,此時人與船之間的關(guān)系就是
依賴。表現(xiàn)在代碼層面,為類B作為參數(shù)被類A在某個method方法中使用瓢捉。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xNDg7QJA-1681228352167)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681115112102.png)]
public class Person {
public void drive(Car car){} //方法參數(shù)
}
class car{}
關(guān)聯(lián)關(guān)系(Association)
關(guān)聯(lián)體現(xiàn)的是兩個類之間語義級別的一種強依賴關(guān)系橱乱,比如我和我的朋友,這種關(guān)系比依賴更強赦政、不存
在依賴關(guān)系的偶然性胜宇、關(guān)系也不是臨時性的,一般是長期性的,而且雙方的關(guān)系一般是平等的桐愉。關(guān)聯(lián)可
以是單向财破、雙向的。表現(xiàn)在代碼層面从诲,為被關(guān)聯(lián)類B以類的屬性形式出現(xiàn)在關(guān)聯(lián)類A中左痢,也可能是關(guān)聯(lián)類
A引用了一個類型為被關(guān)聯(lián)類B的全局變量。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SmurAWG0-1681228352167)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681118127051.png)]
public class Person {
public Address address;
//關(guān)聯(lián)關(guān)系
public void setAddress (Address address){
this.address= address;
}
public Address getAddress (){
return address;
}
}
class Address{}
聚合關(guān)系(Aggregation)
單向盏求,關(guān)聯(lián)關(guān)系的一種抖锥,與關(guān)聯(lián)關(guān)系之間的區(qū)別是語義上的,關(guān)聯(lián)的兩個對象通常是平等的碎罚,聚合則一
般不平等磅废,有一種整體和局部的感覺,實現(xiàn)上區(qū)別不大荆烈。表現(xiàn)在代碼層面拯勉,和關(guān)聯(lián)關(guān)系是一致的,只能
從語義級別來區(qū)分憔购。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SUnTyUvt-1681228352167)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681118815660.png)]
public class Team {
public Person person;
public Team(Person person){
this.person = person;
}
}
Class由Student組成宫峦,其生命周期不同,整體不存在了玫鸟,部分依然存在导绷,當(dāng)前Team解散了,人還在屎飘,
還可以加入別的組妥曲。
組合關(guān)系(Composition)
單向,是一種強依賴的特殊聚合關(guān)系
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mp2hc1w4-1681228352168)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681119222709.png)]
public class Person {
public Head head;
public Body body;
public Person(){
head = new Head();
body = new Body();
}
}
Head钦购,Body檐盟,Arm和Leg組合成People,其生命周期相同押桃,如果整體不存在了葵萎,部分也將消亡。
面對對象內(nèi)存分析
內(nèi)存分析
Java中的對象和數(shù)組是通過引用對其操作的
引用可以理解為一種受限的指針
指針是可以進(jìn)行與整數(shù)做加減運算的唱凯,兩個指針之間也可以進(jìn)行大小比較運算和相減運算羡忘。引用不
行,只能進(jìn)行賦值運算磕昼。引用就是一個變量或?qū)ο蟮膭e名(引用的本質(zhì)是一個對象)卷雕;指針是一個段內(nèi)存空間的地址(指向存
儲一個變量值的空間或一個對象的空間)
內(nèi)存劃分 :
棧
存放:局部變量
先進(jìn)后出,自下而上存儲
方法執(zhí)行完畢掰烟,自動釋放空間
堆
存放new出來的對象
需要垃圾回收器來回收
方法區(qū)
存放:類的信息(代碼)爽蝴、 static變量沐批、字符串常量等
構(gòu)造方法(構(gòu)造器constructor)
構(gòu)造器也叫構(gòu)造方法(constructor),用于對象的初始化蝎亚。構(gòu)造器是一個創(chuàng)建對象時被自動調(diào)用的特殊方
法九孩,目的是對象的初始化。構(gòu)造器的名稱應(yīng)與類的名稱一致发框。Java通過new關(guān)鍵字來調(diào)用構(gòu)造器躺彬,從而返回該類的實例,是一種特殊的方法梅惯。
聲明格式
[修飾符] 類名(形參列表){
//n條語句
}
public Dog(){}
構(gòu)造器4個要點
構(gòu)造器的方法名必須和類名一致宪拥!
構(gòu)造器雖然有返回值,但是不能定義返回類型(返回值的類型肯定是本類)铣减,不能在構(gòu)造器里調(diào)用return她君。
通過new關(guān)鍵字調(diào)用!葫哗!
如果我們沒有定義構(gòu)造器缔刹,則系統(tǒng)會自動定義一個無參的構(gòu)造方法。如果已定義則編譯器不會添加無參數(shù)構(gòu)造方法劣针!
與普通方法一樣校镐,構(gòu)造方法也可以重載
修飾符 final abstract static不能用來修飾構(gòu)造器
作用
初始化對象信息的,不是用于創(chuàng)建對象的
空構(gòu)造
沒有參數(shù)構(gòu)造器叫做無參構(gòu)造
一個類中捺典,如果沒有顯式|手動 加入 任意構(gòu)造器 javac 編譯后 自動加入空構(gòu)造 一旦加入構(gòu)造器 鸟廓,javac 不會加入空構(gòu)造器。
class Dog{
String color;
String name;
//空構(gòu)造
//public Dog(){} 默認(rèn)提供
}
重載
一個類中可以存在多個構(gòu)造器
方法重載: 兩同三不同 同一個類方法名相同襟己,形參類型 個數(shù) 順序不同 構(gòu)造器重載: 只看形參即可 形參類型 個數(shù) 順序不同引谜。調(diào)用時按“就近最優(yōu)原則”
class Dog{
String color;
String name;
//空構(gòu)造
Dog(){}
public Dog(String name,String color){
this.name=name;
this.color=color;
}
public static void main(String[ ] args) {
Dog d1 = new Dog();
Dog d2 = new Dog("小白", "白色");
Dog d3 = new Dog("小灰", "灰色");
}
}
this與static
this關(guān)鍵字
this 即”自己”,代表對象本身稀蟋,誰調(diào)用代表誰 | 指代當(dāng)前對象(new的對象|調(diào)用成員方法的對象)
在成員方法中或構(gòu)造器中隱式的傳遞煌张。作用如下:
- this.屬性避免屬性和形參呐赡、局部變量同名退客,發(fā)生就近原則
- this([實參列表]):構(gòu)造器的首行調(diào)用本類中其他構(gòu)造器。
- 不存在同名問題,哪里有就匹配哪里,如果有局部找局部,如果有成員調(diào)用成員,默認(rèn)相當(dāng)于省略了
- 存在同名問題,就近原則找局部(通過this.調(diào)用成員)
class Web{
//網(wǎng)址
public String url;
public Web(){
System.out.println("構(gòu)造器");
}
public Web(String url){
this(); //this()構(gòu)造器的調(diào)用
this.url =url;//this.屬性 區(qū)分同名問題
}
//賦值
public void setUrl(String url){
this.url =url;
}
/**
屬性與形參 同名链嘀,發(fā)生就近原則
public Web(String url){
url =url;
}
//二者不同名
public Web(String u){
url =u;
}*/
}
注意:靜態(tài)方法中無this萌狂。
多個構(gòu)造器之間不能使用this(實參)相互調(diào)用
static關(guān)鍵字
凡是靜態(tài)的都是屬于類的,與對象無關(guān)的怀泊,先于對象存在的茫藏。可用于修飾屬性霹琼、方法务傲、塊凉当。
在類中,用static聲明的成員變量為靜態(tài)成員變量 ,或者叫做: 類屬性售葡,類變量看杭。
- 它為該類的公用變量,屬于類挟伙,被該類的所有實例共享楼雹,在類被載入時被顯式初始化。
- 對于該類的所有對象來說尖阔,static成員變量只有一份贮缅。被該類的所有對象共享!介却!
- 可以使用”對象.類屬性”來調(diào)用谴供。不過,一般都是用“類名.類屬性”
- static變量置于方法區(qū)中齿坷!
用static聲明的方法為靜態(tài)方法
- 不需要對象憔鬼,就可以調(diào)用(類名.方法名)
- 在調(diào)用該方法時,不會將對象的引用傳遞給它胃夏,所以在static方法中不可直接訪問非static的成員轴或,
但是可以通過對象使用。- 靜態(tài)方法不能以任何方式引用this和super關(guān)鍵字
static修飾成員位置的塊 : 靜態(tài)塊
static修飾成員位置的類 : 靜態(tài)的內(nèi)部類
class StaticDemo01 {
static int id;//靜態(tài)變量
int age; //成員變量
public static void main(String[] args) {
//靜態(tài)的內(nèi)容可以直接使用
System.out.println("id1="+id); //id1=0
System.out.println("id2="+StaticDemo01.id); //id2=0
test();
//通過對象使用成員
StaticDemo01 sd=new StaticDemo01();
System.out.println("age="+sd.age);//age=0
}
/*
* 靜態(tài)方法
*/
public static void test(){
id++;
}
/*
* 成員方法 使用靜態(tài)和非靜態(tài)的內(nèi)容
*/
public void test2(){
//非靜態(tài)的方法中可以直接使用成員內(nèi)容,可以通過對象使用
age++;
id++;
}
}
注意
- 靜態(tài)內(nèi)容中只能直接使用靜態(tài)內(nèi)容,通過對象使用成員內(nèi)容
- 成員內(nèi)容中可以直接使用靜態(tài)內(nèi)容,可以直接使用成員內(nèi)容,也可以通過對象使用
注意:
成員是屬于對象的,需要通過對象使用成員,因為成員變量在對象的堆內(nèi)存中,先有對象才有成員
static是靜態(tài)的,靜態(tài)的內(nèi)容是屬于類的,靜態(tài)變量在靜態(tài)區(qū)中,是獨一份的,所有對象共享的
加載初始順序 : 先靜態(tài)后成員
靜態(tài)變量在類第一次加載完成之后就初始化,在靜態(tài)區(qū)中,獨一份
調(diào)用特點
在靜態(tài)環(huán)境中,可以直接調(diào)用靜態(tài)內(nèi)容,不能直接調(diào)用成員,需要依賴對象調(diào)用
在成員環(huán)境中,可以直接調(diào)用靜態(tài),可以直接調(diào)用成員(非靜態(tài))
分類 :
定義在成員位置的變量: 成員變量
被static修飾的成員變量 : 類變量|靜態(tài)變量 不被static修飾的成員變量 : 實例變量
定義在成員位置的方法 : 成員方法
被static修飾的成員方法 : 靜態(tài)方法|類方法 不被static修飾的成員方法 : 實例方法
block與debug
block
塊{},在java中自成作用域仰禀,可以分為
靜態(tài)代碼塊 | 構(gòu)造代碼塊 | 普通語句塊 | 同步代碼塊 | |
---|---|---|---|---|
聲明位置 | 類中照雁,方法外 | 類中,方法外 | 方法中 | fynchronized() |
作用 | 整個類進(jìn)行某些初始化操作(靜態(tài)屬性賦值...) | 構(gòu)造代碼塊是為對象初始化操作(為靜態(tài)或非靜態(tài)成員屬性賦值...) | 聲明一些臨時變量等.. | 控制并發(fā) |
執(zhí)行時機 | 類第一次加載時,只執(zhí)行一次,如果多個靜態(tài)塊,從上到下依次執(zhí)行 | 創(chuàng)建對象時,執(zhí)行構(gòu)造器代碼之前執(zhí)行,如有多個,從上到下依次執(zhí)行 | 跟隨方法執(zhí)行 | 跟對方法執(zhí)行 |
注意:
同一作用域內(nèi),變量不能同名
構(gòu)造塊代碼在編譯期間,會被編譯到要執(zhí)行的構(gòu)造器內(nèi)部,構(gòu)造器代碼之前
如果存在多個構(gòu)造塊,從上到下依次執(zhí)行
靜態(tài)塊在類第一次加載完成之后就執(zhí)行,并且只執(zhí)行一次,不能手動調(diào)用
如果存在多個靜態(tài)塊,從上到下依次執(zhí)行
注意
- 類第一次被載入時先執(zhí)行static代碼塊答恶;類多次載入時饺蚊,static代碼塊只執(zhí)行一次;static塊經(jīng)常用
- 來進(jìn)行static變量的初始化悬嗓。
- 是在類初始化時執(zhí)行污呼,不是在創(chuàng)建對象時執(zhí)行。
- 靜態(tài)初始化塊中不能訪問非static成員包竹。
- 構(gòu)造塊被被編譯到將要執(zhí)行的構(gòu)造器代碼之前執(zhí)行
靜態(tài)塊燕酷,僅在類的第一次使用時加載。
構(gòu)造塊周瞎,先于構(gòu)造器執(zhí)行苗缩,每創(chuàng)建一個對象執(zhí)行一次
debug
在學(xué)習(xí)或開發(fā)過程中,遇到bug是避免不了的,為了能夠快速調(diào)試,可以使用debug調(diào)試工具。
調(diào)試一個Java程序非常簡單的声诸,主要有設(shè)置斷點酱讶、啟動調(diào)試、單步執(zhí)行彼乌、結(jié)束調(diào)試幾步泻肯。
作用
追蹤程序的執(zhí)行流程
觀察程序執(zhí)行過程中變量的變化情況
快速定位問題出現(xiàn)的位置|異常出現(xiàn)的位置
學(xué)習(xí)第三框架的源碼
debug界面窗口
- 斷點:在左邊行號欄單擊左鍵渊迁,斷點行的顏色可自己去設(shè)置。
- Debug窗口:訪問請求到達(dá)第一個斷點后灶挟,會自動激活Debug窗口宫纬。如果沒有自動激活,可以去設(shè)
置里設(shè)置膏萧。- Debugger->debug調(diào)試窗口,Console->控制臺
- 調(diào)試按鈕:調(diào)試的主要功能就對應(yīng)著這幾個按鈕漓骚,鼠標(biāo)懸停在按鈕上可以查看對應(yīng)的快捷鍵。
- 方法調(diào)用棧:這里顯示了該線程調(diào)試所經(jīng)過的所有方法榛泛。
- Variables:在變量區(qū)可以查看當(dāng)前斷點之前的當(dāng)前方法內(nèi)的變量蝌蹂。
- 服務(wù)按鈕:可以在這里關(guān)閉/啟動服務(wù),設(shè)置斷點等曹锨。
debug調(diào)試使用步驟
設(shè)置斷點
啟動調(diào)試
單步執(zhí)行
調(diào)試按鈕說明 Show Execution Point (Alt + F10):如果你的光標(biāo)在其它行或其它頁面孤个,點擊這個按鈕可跳轉(zhuǎn) Step Over (F8):步過,一行一行地往下走沛简,如果這一行上有方法不會進(jìn)入方法齐鲤。 Step Into (F7):步入,如果當(dāng)前行有方法椒楣,可以進(jìn)入方法內(nèi)部给郊,一般用于進(jìn)入自定義方法內(nèi),不會進(jìn)入官方類庫的方法捧灰。 Force Step Into (Alt + Shift + F7):強制步入淆九,能進(jìn)入任何方法,查看底層源碼的時候可以用這個進(jìn)入官方類庫的方法毛俏。 Step Out (Shift + F8):步出炭庙,從步入的方法內(nèi)退出到方法調(diào)用處,此時方法已執(zhí)行完畢煌寇,只是還沒有完成賦值焕蹄。 Drop Frame (默認(rèn)無):回退斷點,后面章節(jié)詳細(xì)說明阀溶。 Run to Cursor (Alt + F9):運行到光標(biāo)處腻脏,你可以將光標(biāo)定位到你需要查看的那一行,然后使用這個功能淌哟,代碼會運行至光標(biāo)行迹卢,而不需要打斷點辽故。
- 結(jié)束調(diào)試
package與import
package
概述
package存在的意義是防止命名沖突造成使用不便徒仓。
包機制
- 管理項目中眾多資源
- 提供多重的命名空間
package類似一個文件夾,文件夾內(nèi)有各種文件誊垢。package與package的附屬關(guān)系用“.”連接掉弛,類似父文件
夾中的子文件夾症见。比如說 java.lang.String就是java文件夾中的lang文件夾中的String文件。
java.io.InputStream則是java文件夾中的io文件夾中的InputStream文件殃饿。同一個文件夾內(nèi)無法存在同名的文件谋作,而不同名的文件夾里允許存在同名文件,因此不同文件夾(即不
同package中允許出現(xiàn)相同class名)乎芳。為了便于管理大型軟件系統(tǒng)中數(shù)目眾多的類遵蚜,解決類的命名沖突問題,Java 引入包(package)機制奈惑,提
供類的多重類命名空間吭净。
格式
一般的命名為:公司域名倒寫+功能名|模塊名。
package 語句作為 Java 源文件的第一條語句肴甸,指明該文件中定義的類所在的包寂殉。(若缺省該語句,則指
定為無名包)原在。
package pkg1[.pkg2[.pkg3…]];
package com.java01.test;
Java 編譯器把包對應(yīng)于文件系統(tǒng)的目錄管理友扰,package 語句中,用’.’來指明包(目錄)的層次庶柿,例如使
用語句: package com.java01 ,則該文件中所有的類位于.\com\java01 目錄下
注意
不要定義與 jdk 相同的包村怪,相同的類,否則會引起很多你覺得莫名其妙的問題
寫項目時都要加包浮庐,不要使用默認(rèn)包实愚。
com.oop和com.oop.test,這兩個包沒有包含關(guān)系兔辅,是兩個完全獨立的包腊敲。只是邏輯上看起來后者
是前者的一部分。
import
如果一個類存在包名维苔,則在其他包下使用該類時碰辅,必須使用全額限定名(簡稱全名或完整類名,
com.java01.MyClass)介时,編譯器才能找到該類没宾;也可以使用 import 在文件的開頭引入要使用到的類。
import java.util.Scanner;
import java.io.*; //模糊匹配當(dāng)前io包下所有類
public class ImportDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in); //因為使用import關(guān)鍵字導(dǎo)包,可以使用
java.util.ArrayList list=new java.util.ArrayList(); //權(quán)限定名
//導(dǎo)入集合 注意:導(dǎo)入是不要導(dǎo)錯包
//使用*,模糊匹配
File file=new File("D://test.txt");
InputStream isInputStream=new FileInputStream(file);
}
}
不需要使用 import 的類有:
- 語言包 (java.lang)下的類 (String,System...)
- 同包下的類
靜態(tài)導(dǎo)入:
import 語句不僅可以導(dǎo)入類沸柔,還增加了導(dǎo)入靜態(tài)方法的功能
//導(dǎo)入靜態(tài)屬性
import static java.lang.Math.PI;
import static java.lang.System.out;
//導(dǎo)入靜態(tài)方法
import static java.lang.Math.sin;
public class ImportDemo {
public static void main(String[] args) {
out.println(PI);
sin(1.1);
}
}
總結(jié)
如果想將一個類放入包中循衰,在類的源文件首行使用package
必須保證該類的 class 文件位于正確的目錄下
另外的類想訪問的話:
寫全名
引入
模糊匹配(會將該包下所有用到的類引入進(jìn)來),會降低編譯速度褐澎,但是不會影響運行
速度
具體類名
靜態(tài)導(dǎo)入
- 同包下的類不需要導(dǎo)入
JDK中常用的包簡單介紹
- java.lang –語言包:語言中常用的功能会钝,如:String、Math、System迁酸、Integer先鱼、Thread…
- java.util – 工具包:提供一些實用的工具類,如:容器(List奸鬓、Set焙畔、Map…),日期類
- java.io – 輸入輸出包:提供操作讀取文件的相關(guān)類,如:File串远、InputStream宏多、OutputStream…
- java.net – 網(wǎng)絡(luò)包: 操 作 遠(yuǎn) 程 資 源 的 類 , 如:InetSocketAddress澡罚、 DatagramPacket绷落、
ServerSocket…- java.sql – 數(shù)據(jù)庫包:操作JDBC的類,Connection始苇、Statement砌烁、ResultSet….
垃圾回收機制(gc)
Garbage Collection 垃圾回收機制
每個程序員都遇到過內(nèi)存溢出的情況,程序運行時催式,內(nèi)存空間是有限的函喉,那么如何及時的把不再使用的
對象清除將內(nèi)存釋放出來,這就是GC要做的事荣月。
jvm內(nèi)存結(jié)構(gòu)分為五大區(qū)域:
程序計數(shù)器管呵、虛擬機棧、本地方法棧哺窄、堆區(qū)捐下、方法區(qū)。
其中虛擬機棧萌业、本地方法棧與程序計數(shù)器這3個區(qū)域隨線程而生坷襟、隨線程而滅,因此就不需要考慮過多內(nèi)存垃圾回收問題生年,因為一個方法調(diào)用結(jié)束或者線程結(jié)束時婴程,內(nèi)存自然就跟隨著回收了。
我們就把重點放在方法區(qū)與堆區(qū)抱婉,這部分內(nèi)存的分配和回收是動態(tài)的档叔,正是垃圾收集器所需關(guān)注的部分。GC主要做了清理對象蒸绩,整理內(nèi)存的工作衙四。
不同語言下對象空間的釋放:
傳統(tǒng)的C/C++語言,需要程序員負(fù)責(zé)回收已經(jīng)分配內(nèi)存患亿。顯式回收垃圾回收的缺點:
程序忘記及時回收传蹈,從而導(dǎo)致內(nèi)存泄露,降低系統(tǒng)性能。
程序錯誤回收程序核心類庫的內(nèi)存卡睦,導(dǎo)致系統(tǒng)崩潰宴胧。
Java語言不需要程序員直接控制內(nèi)存回收漱抓,是由JRE在后臺自動回收不再使用的內(nèi)存表锻,稱為垃圾回收機制(Garbage Collection)。
可以提高編程效率乞娄。
保護(hù)程序的完整性瞬逊。
其開銷影響性能。Java虛擬機必須跟蹤程序中有用的對象仪或,確定哪些是無用的确镊。
垃圾回收機制關(guān)鍵點
垃圾回收機制只回收J(rèn)VM堆內(nèi)存里的對象空間。
對其他物理連接范删,比如數(shù)據(jù)庫連接蕾域、輸入流輸出流、Socket連接無能為力
現(xiàn)在的JVM有多種垃圾回收實現(xiàn)算法到旦,表現(xiàn)各異旨巷。
垃圾回收發(fā)生具有不可預(yù)知性,程序無法精確控制垃圾回收機制執(zhí)行添忘。
可以將對象的引用變量設(shè)置為null采呐,暗示垃圾回收機制可以回收該對象。
程序員可以通過System.gc()或者Runtime.getRuntime().gc()來通知系統(tǒng)進(jìn)行垃圾回收搁骑,會有一些效果斧吐,但是系統(tǒng)是否進(jìn)行垃圾回收依然不確定。
垃圾回收機制回收任何對象之前仲器,總會先調(diào)用它的finalize方法(如果覆蓋該方法煤率,讓一個新的引用
變量重新引用該對象,則會重新激活對象)乏冀。
永遠(yuǎn)不要主動調(diào)用某個對象的finalize方法涕侈,應(yīng)該交給垃圾回收機制調(diào)用。
封裝(encapsulation)
概念
我們程序設(shè)計要追求“ 高內(nèi)聚煤辨,低耦合”裳涛。高內(nèi)聚就是類的內(nèi)部數(shù)據(jù)操作細(xì)節(jié)自己完成,不允許外部干
涉众辨;低耦合:僅暴露少量的方法給外部使用端三。利用抽象數(shù)據(jù)類型將數(shù)據(jù)和基于數(shù)據(jù)的操作封裝在一起,
使其構(gòu)成一個不可分割的獨立實體,數(shù)據(jù)被保護(hù)在抽象數(shù)據(jù)類型的內(nèi)部,盡可能地隱藏內(nèi)部的細(xì)節(jié)弓候,只保留一些對外接口使之與外部發(fā)生聯(lián)系晒哄。系統(tǒng)的其他部分只有通過包裹在數(shù)據(jù)外面的被授權(quán)的操作來與這個抽象數(shù)據(jù)類型交流與交互奸焙。也就是說掂器,用戶無需知道對象內(nèi)部方法的實現(xiàn)細(xì)節(jié)格嘁,但可以根據(jù)對象提供的外部接口(對象名和參數(shù))訪問該對象这橙。
作用
- 實現(xiàn)了專業(yè)的分工欢摄。將能實現(xiàn)某一特定功能的代碼封裝成一個獨立的實體后熬丧,各程序員可以在需要
的時候調(diào)用,從而實現(xiàn)了專業(yè)的分工,即工作中的分模塊怀挠、分功能開發(fā)析蝴。- 隱藏信息,實現(xiàn)細(xì)節(jié)绿淋。通過控制訪問權(quán)限可以將可以將不想讓客戶端程序員看到的信息隱藏起來闷畸,
如某客戶的銀行的密碼需要保密,只能對該客戶開發(fā)權(quán)限吞滞。
JavaBean
在編寫 javabean 中的有一些常用的規(guī)則如
- 類是公共的public
- 至少提供一個空構(gòu)造
- 提供一對公共的訪問方式屬性盡可能私有化 private
- 設(shè)置器:setter 為私有屬性設(shè)置值
- 訪問器:getter 獲取私有屬性的值
public class Person { //姓名
private String name; //年齡
private int age; //性別
private boolean sex;
public Person() {
}
//setter與getter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
}
注意 : 以后所定義的所有實體類,屬性都需要私有化,并提供一對公共的訪問方式
面向?qū)ο?繼承(inheritance)
繼承
繼承的本質(zhì) : 是對某一批類的抽象佑菩,從而實現(xiàn)對現(xiàn)實世界更好的建模。
繼承的作用 : 使用繼承可以提高代碼的復(fù)用性裁赠。
如何使用繼承 : 使用
extends
關(guān)鍵字即可殿漠。extends 關(guān)鍵字的意思是“擴展”。子類是父類的延續(xù)+擴展组贺。
java 中使用 extends 關(guān)鍵字實現(xiàn)類的繼承機制凸舵,語法規(guī)則
<modifier> class <name> [extends <superclass>]{}
//父類 class Person{ public String name; public int age; public void sleep(){ System.out.println("休息"); } }
//子類 //教師類 class Teacher extends Person{ public String subject; public Teacher() { } public void teach(){ System.out.println("傳授知識"); } } //學(xué)生類 class Student extends Person{ public String school; public Student() { } public void study(){ System.out.println("在知識的海洋暢游!"); } }
注意
子類繼承父類的成員變量和成員方法,但不繼承父類的構(gòu)造方法
java中只有單繼承 失尖,一個子類只能存在一個直接父類
優(yōu)點 : 簡單
缺點 : 不便于后期維護(hù)
java中的多繼承啊奄,可以通過接口來實現(xiàn)
如果定義一個類時,沒有調(diào)用extends掀潮,則它的父類是:java.lang.Object菇夸。
繼承的特點
優(yōu)點
通過繼承可以簡化類的定義,實現(xiàn)代碼的重用|提高代碼復(fù)用性
可以更好的擴展程序
子類一旦繼承父類,可以有權(quán)使用父類中的成員仪吧,也可以擴展定義子類獨有內(nèi)容
java是單繼承繼承庄新,實現(xiàn)簡單
缺點
子類與父類之間緊密耦合(耦合度高),子類依賴于父類的實現(xiàn)薯鼠,子類缺乏獨立性择诈。
不便于后期維護(hù)
單繼承一個子類只能有一個父類,不夠靈活,不便于后期維護(hù)
權(quán)限修飾符
public: 一覽無遺;
protected:子承父業(yè) (兒子自己使用)出皇;
default :家庭和睦羞芍;
private :占為已有
關(guān)鍵字 | 同一個類 | 同一個包中 | 不同包下子類 | 所以類 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
public class YJXXT_Modefier{
private int privateField;
int privateField; // default 不能寫
protected int privateField;
public int privateField;
}
注意 :
訪問權(quán)限修飾符都是成員修飾符,只能修飾成員不能修飾局部
default是默認(rèn)的,沒有顯示的通過其他訪問權(quán)限修飾符進(jìn)行修飾,默認(rèn)通過default修飾
能夠用來修飾類的訪問權(quán)限修飾符 : public | default
訪問被protected修飾的成員
1. 同包類下訪問 2. 不同包下的子類中,通過繼承關(guān)系訪問
重寫Override
父類的功能實現(xiàn)不滿足子類的要求,可以在子類中按需改寫郊艘,這就是方法的重寫荷科。
實現(xiàn)重寫的三個條件
不同的兩個類
繼承關(guān)系|實現(xiàn)關(guān)系
方法簽名相同
@Override:注解,強制檢查是否為重寫方法
注意
子類重寫的方法會對父類的方法進(jìn)行屏蔽唯咬。
當(dāng)子類對象調(diào)用時,會調(diào)用子類中重寫的方法畏浆,子類沒有找父類胆胰。
public class OverrideTest { public static void main(String[] args) { Sicong sicong=new Sicong(); sicong.getMoney(); //調(diào)用子類中重寫方法 } } //父類 class Jianlin{ public void getMoney(){ System.out.println("先定一個小目標(biāo),賺他個一個億"); } } //子類 class Sicong extends Jianlin{ @Override //強制檢查是否為重寫方法 public void getMoney(){ super.getMoney();//在父類的原賺錢方法上擴展新功能,老功能不變 System.out.println("我認(rèn)識的人都沒我有錢"); } }
重寫的三個"="
“==”:方法簽名完全相等。
“≤”:返回值類型
基本數(shù)據(jù)類型|void : 子類中的重寫方法的返回值類型==父類中被重寫方法的返回值類型
引用數(shù)據(jù)類型 : 子類中重寫方法的返回值類型<=父類中被重寫方法的返回值類型
“≥”:訪問權(quán)限修飾符
子類中重寫方法的訪問權(quán)限修飾符>=父類中被重寫方法的訪問權(quán)限修飾符
以下修飾符刻获、修飾的內(nèi)容不能重寫:
- private修飾的方法不能被重寫
- final修飾的方法不能被重寫
- static修飾的方法不能被重寫(子類如果出現(xiàn)和父類靜態(tài)方法同名情況,那么子類中的方法也必須為靜態(tài)的)
重寫和重載的區(qū)別
實現(xiàn)重載條件 :
- 一個類中的多個方法
- 方法名相同
- 參數(shù)列表不同|方法簽名不同
- 參數(shù)個數(shù)不同
- 參數(shù)類型不同
- 不同類型參數(shù)的順序不同
實現(xiàn)重寫的條件 :
- 兩個類中的兩個方法
- 繼承|實現(xiàn)關(guān)系
- 方法簽名相同
使用重寫前提需求:當(dāng)子類對從父類中所繼承的功能滿意,但是功能的實現(xiàn)不滿意的時候,在子類中重寫實現(xiàn)這個功能->重寫
private修飾的成員是否能被繼承? 能被繼承但是無權(quán)訪問
靜態(tài)的內(nèi)容是否能夠被繼承? 能
父類中的構(gòu)造器是否能被繼承? 不能
super關(guān)鍵字
super
super是指向父類的引用蜀涨。
super可以在子類構(gòu)造器中調(diào)用父類某個構(gòu)造器
如果構(gòu)造方法沒有顯示地調(diào)用父類的構(gòu)造方法,那么編譯器會自動為它加上一個默認(rèn)的super()方法調(diào)
用将鸵。如果父類由沒有默認(rèn)的無參構(gòu)造方法勉盅,編譯器就會報錯佑颇,super()語句必須是構(gòu)造方法的第一個子句顶掉。
super可以用來區(qū)分子父類中同名成員
如果不存在同名問題,可以直接在子類中調(diào)用父類內(nèi)容挑胸,super默認(rèn)省略
如果存在同名問題,在子類中調(diào)用同名成員,默認(rèn)this.恒源 調(diào)用當(dāng)前子類同名成員,先要調(diào)用父類同名成員,
必須定義為super.成員
//父類
public class Animal {
int eye = 2;
public Animal(){
super();
System.out.println("動物");
}
public void run(){
System.out.println("動物有不同走路方式");
}
public static void main(String[] args) {
Bird b = new Bird();
b.run();
}
}
//子類
class Bird extends Animal{
public Bird(){
super();
System.out.println("鳥類");
}
public void run() {
super.run(); // 通過super可以用父類方法和屬性
System.out.println("鳥是飛飛飛飛飛飛");
System.out.println("鳥類有"+super.eye+"只眼睛");
}
}
Bird--> Animal --> Object 圖形分析如下
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GPhgNyWB-1681228352169)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1681184580359.png)]
構(gòu)造方法調(diào)用順序
根據(jù)super的說明痒筒,構(gòu)造方法第一句 總是:super(…)來調(diào)用父類對應(yīng)的構(gòu)造方法。
先向上追溯到Object茬贵,然后再依次向下執(zhí)行類的初始化塊和構(gòu)造方法簿透,直到當(dāng)前子類為止。
this和super之間的區(qū)別
相同點
- this和super都能用來調(diào)動其他共構(gòu)造器,都要在首行出現(xiàn)
- this和super都可以用來區(qū)分同名問題,不區(qū)分同名時候可以省略
- this和super都指的是對象解藻,所以老充,均不可以在static環(huán)境中使用。包括:static變量,static方法螟左,
static語句塊啡浊。
不同點
- this(參數(shù))構(gòu)造器第一行調(diào)用本類中其他構(gòu)造器,super(參數(shù))構(gòu)造器第一行調(diào)用父類中某個構(gòu)造器
- this用來區(qū)分成員和局部同名問題,super用來區(qū)分子父類中同名問題
注意
this和super不能同時出現(xiàn)在一個構(gòu)造函數(shù)里面,因為this必然會調(diào)用其它的構(gòu)造函數(shù)胶背,其它的構(gòu)造
函數(shù)必然也會有super語句的存在巷嚣,所以在同一個構(gòu)造函數(shù)里面有相同的語句,就失去了語句的意
義钳吟,編譯器也不會過廷粒。從本質(zhì)上講,this是一個指向本對象的指針, 然而super是一個Java關(guān)鍵字
final關(guān)鍵字
final 表示最終的红且。
final可以用來修飾變量坝茎,方法,類暇番。
修飾變量嗤放,被final修飾的變量為常量
final int x=3; //x=4; 常量不能改變
修飾方法,被final修飾的方法不能被重寫
final void eat() { … }
修飾類奔誓,被final修飾的類不能被繼承(太監(jiān)類)
final class Person{ … }
Object類
Object 類是所有 Java 類的根基類
如果在類的聲明中未使用 extends 關(guān)鍵字指明其基類斤吐,則默認(rèn)基類為 Object 類
toString
當(dāng)打印對象的引用時,默認(rèn)調(diào)用toString()方法
默認(rèn)返回:包名+類名+@+哈希碼(根據(jù)對象的內(nèi)存地址生成,唯一不重復(fù))
可以重寫,實現(xiàn)義字符串的形式返回對對象(打印對象所有成員屬性的值)
//Object類中的toString : public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
User p1=new User("張三",20); System.out.println(p1); //相當(dāng)于 System.out.println(p1.toString());
當(dāng)輸出對象的字符串表現(xiàn)形式時候,想要輸出的是對象的所有屬性值而非地址值,這時可以在子類根據(jù)所有的屬性值進(jìn)行重寫===>通過快捷鍵生成
注意 : 以后所定義的所有實體類都需要根據(jù)所有屬性值重寫toString方法
equals
比較相等是否相等
默認(rèn)地址比較(”第一個盒子的比較”)
重寫可以是實現(xiàn)比較兩對象的內(nèi)容是否一致
object1.equals(object2) 如 : p1.equals(p2) 比較所指對象的內(nèi)容是否一樣,具體看equals的方法重寫 object1 == object2 如:p1==p2 比較p1和p2的值即內(nèi)存地址是否相等搔涝,即是否是指向同一對象。
注意:自定義類須重寫equals()和措,否則無法實現(xiàn)比較其內(nèi)容
class User{ String name; int age; public User() { // TODO Auto-generated constructor stub } public User(String name, int age) { super(); this.name = name; this.age = age; } //重寫toString @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } //重寫equals @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; User other = (User) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
==與equals之間的區(qū)別
== 比較任意類型的數(shù)據(jù)是否相等
基本數(shù)據(jù)類型(數(shù)據(jù)值) : 比較就是數(shù)據(jù)值
引用數(shù)據(jù)類型(對象) : 比較對象的地址值
equals 比較引用數(shù)據(jù)類型的數(shù)據(jù)
如果使用Object類中equals方法的實現(xiàn),默認(rèn)根據(jù)==實現(xiàn)比較,比較對象地址值
如果調(diào)用子類中重寫的equals方法,可以實現(xiàn)比較對象的內(nèi)容(屬性值)
多態(tài)(polymorphism)
概述
多態(tài)polymorphism庄呈,主要是用來實現(xiàn)動態(tài)聯(lián)編的,換句話說派阱,就是程序的最終狀態(tài)只有在執(zhí)行過程中才被決定而非在編譯期間就決定了诬留。這對于大型系統(tǒng)來說能提高系統(tǒng)的靈活性和擴展性。
一種事物的多種形態(tài)|多種表現(xiàn)形式-->行為多態(tài)(一個功能的不同實現(xiàn)方式)
引用變量的兩種類型:
- 編譯時類型(模糊一點贫母,一般是一個父類)
- 由聲明時的類型決定文兑。
- 運行時類型(運行時,具體是哪個子類就是哪個子類)
- 由實際對應(yīng)的對象類型決定
多態(tài)的存在要有3個必要條件:要有繼承腺劣,要有方法重寫绿贞,父類引用指向子類對象
注意 : 如果編譯時類型和運行時類型不一致,就可能會造成多態(tài)橘原。
使用
多態(tài)是方法的多態(tài)籍铁,屬性沒有多態(tài)性。
public class TestPolym {
public static void main(String[] args) {
//父類引用指向子類對象
Animal animal = new Dog();
System.out.println(animal.age); //屬性調(diào)用時趾断,仍然是基類的屬性拒名。屬性沒有多態(tài)!
animal.shout(); //行為存在多態(tài)
animalCry(new Dog());
//傳的具體是哪一個類就調(diào)用哪一個類的方法芋酌。大大提高了程序的可擴展性增显。
//如果沒有多態(tài),我們這里需要寫很多重載的方法脐帝。如果增加一種動物同云,就需要重載一種動物的喊叫方法。非常麻煩腮恩。
//有了多態(tài)梢杭,只需要增加這個類繼承Animal基類就可以了。
animalCry(new Cat());
}
static void animalCry(Animal a){
a.shout();
}
}
class Animal {
int age=10;
public void shout(){
System.out.println("叫了一聲秸滴!");
}
}
class Dog extends Animal {
int age=28;
public void shout() {
System.out.println("旺旺旺武契!");
}
public void gnawBone(){
System.out.println("我再啃骨頭");
}
}
class Cat extends Animal {
int age=18;
public void shout() {
System.out.println("喵喵喵喵!");
}
}
普通引用調(diào)用成員(成員變量|成員方法)
能夠調(diào)用子類中的所有成員,以及子類從父類中繼承的成員
多態(tài)調(diào)用成員(成員變量|成員方法) :
多態(tài)調(diào)用成員變量:編譯運行看父類|左邊|引用
多態(tài)調(diào)用成員方法:編譯看父類|左邊|類型,運行找子類|右邊|對象
多態(tài)需要配合方法的重寫才有意義,會調(diào)用子類中重寫的方法對子類新增成員不可見
引用數(shù)據(jù)類型的類型轉(zhuǎn)換(Cast)
標(biāo)準(zhǔn)語法格式 : 對應(yīng)類型的數(shù)據(jù)賦值給對應(yīng)類型的變量
數(shù)據(jù)類型轉(zhuǎn)換 : 基本數(shù)據(jù)類型
自動類型提升 : 小 --> 大
強制類型轉(zhuǎn)換 : 大 --> 小
小范圍類型 變量 = (小范圍類型)大范圍類型數(shù)據(jù);
轉(zhuǎn)型 :引用數(shù)據(jù)類型
子類 : 小 父類 : 大
向上轉(zhuǎn)型 : 小 --> 大
父類 引用 = new 子類(); --> 多態(tài)
向下轉(zhuǎn)型 : 大 --> 小
子類 變量 = (子類)父類類型數(shù)據(jù);
注意 : 當(dāng)想要通過多態(tài)引用調(diào)用子類中新增成員時候,可以先向下轉(zhuǎn)型,再調(diào)用
注意:
編寫程序時荡含,如果想調(diào)用運行時類型的方法咒唆,只能進(jìn)行類型轉(zhuǎn)換。不然通不過編譯器的檢查释液。但是如果兩個沒有關(guān)聯(lián)的類進(jìn)行強制轉(zhuǎn)換全释,會報: ClassCastException 。比如:本來是狗误债,我把它轉(zhuǎn)成貓浸船。就
會報這個異常妄迁。
實現(xiàn)避免類型轉(zhuǎn)換異常的出現(xiàn)引用 instanceof 類型 : 判斷前面的引用是否是指向后面類型的對象|子類對象,如果是就返回true,不是就返回false
instanceof
使用前提
在向下轉(zhuǎn)型的時候,為了避免類型轉(zhuǎn)換異常 ClassCastException 的出現(xiàn),可以使用instanceof進(jìn)行判斷。
instanceof是Java的一個二元操作符李命,和==登淘,>,<是同一類封字。由于它是由字母組成的黔州,所以也是Java的
保留關(guān)鍵字。它的作用是測試它左邊的對象是否是它右邊的類的實例阔籽,返回boolean類型的數(shù)據(jù)流妻。Animal animal = new Dog(); System.out.println(animal instanceof Animal); System.out.println(animal instanceof Cat); System.out.println(animal instanceof Dog); //先判斷后轉(zhuǎn)型 if(animal instanceof Dog){ Dog dog = (Dog) animal; }
抽象類與抽象方法
抽象類用來描述一種類型應(yīng)該具備的基本特征與功能, 具體如何去完成這些行為由子類通過方法重寫來完成笆制。
抽象方法指只有功能聲明绅这,沒有功能主體實現(xiàn)的方法。
具有抽象方法的類一定為抽象類项贺。通過抽象類君躺,我們就可以做到嚴(yán)格限制子類的設(shè)計峭判,使子類之間更加通用开缎。
定義
抽象方法 : 不需要方法體的方法,需要用 abstract 關(guān)鍵字修飾林螃。只能出現(xiàn)在抽象類中奕删。
public abstract void shout();
抽象類 : 被 abstract 修飾的類為抽象類。
public abstract class Canine{ private String brand; public Canine(){} public Canine(String brand){ this.brand = brand; } //抽象方法 public abstract void shout(); //具體方法 public void sleep(){ System.out.println("閉著眼睛睡覺!!!"); } }
抽象類的使用要點
有抽象方法的類只能定義能抽象類
抽象類不能實例化疗认,即不能用new來實例化抽象類完残。
抽象類可以包含屬性、方法横漏、構(gòu)造方法谨设。但是構(gòu)造方法不能用來new實例,只能用來被子類調(diào)用缎浇。
抽象類只能用來繼承扎拣。
抽象方法必須被子類實現(xiàn)。
abstract不可以與private,final,static,native一起使用
抽象類和普通父類的區(qū)別
就在于包含抽象方法素跺,抽象方法必須被子類實現(xiàn)二蓝,從而可以對子類的設(shè)計進(jìn)
行規(guī)范。作用
實現(xiàn)了規(guī)范和具體實現(xiàn)的分離指厌。通過 abstract 方法定義規(guī)范刊愚,然后要求子類必須定義具體實現(xiàn)。引用
變量仍然可以定義為抽象類踩验,這樣就可以規(guī)范地實現(xiàn)多態(tài)了鸥诽。
接口
特殊的抽象類
抽象方法的結(jié)合
是一種引用數(shù)據(jù)類型
類只能單繼承,接口可以多實現(xiàn)
定義開發(fā)規(guī)范
實現(xiàn)解耦(降低耦合度)
接口就是比“抽象類”還“抽象”的“抽象類”商玫,可以更加規(guī)范的對子類進(jìn)行約束。
全面地專業(yè)地實現(xiàn)了:規(guī)范和具體實現(xiàn)的分離牡借。
抽象類還提供某些具體實現(xiàn)决帖,接口 不提供任何實現(xiàn) ,接口中所有方法都是抽象方法蓖捶。接口是完全面向規(guī)范的地回,規(guī)定了一批類具有的公共方法規(guī)范。
從接口的實現(xiàn)者角度看俊鱼,接口定義了可以向外部提供的服務(wù)刻像。
從接口的調(diào)用者角度看,接口定義了實現(xiàn)者能提供那些服務(wù)并闲。
接口是兩個模塊之間通信的標(biāo)準(zhǔn)细睡,通信的規(guī)范。
如果能把你要設(shè)計的系統(tǒng)之間模塊之間的接口定義
好帝火,就相當(dāng)于完成了系統(tǒng)的設(shè)計大綱溜徙,剩下的就是添磚加瓦的具體實現(xiàn)了。大家在工作以后犀填,做系統(tǒng)時往往就是使用 “面向接口” 的思想來設(shè)計系統(tǒng)蠢壹。
類類 -> 一個類 繼承 另外一個類
類抽象類 > 一個類繼承另一個抽象類 (類要重寫抽象方法)
類接口 -> 一個類實現(xiàn)若干個接口(類種需要重寫所有接口種的所有方法)
接口接口 -> 一個接口繼承若干個接口
定義接口
[權(quán)限修飾符] interface 接口名 [extends 父接口1,父接口2…] { 常量定義九巡; 抽象方法定義图贸; }
- 訪問修飾符:只能是public或默認(rèn)。
- 接口名:和類名采用相同的命名機制
- extends:接口可以多繼承
- 常量:接口中的屬性只能是常量冕广,總是:public static final 修飾疏日。不寫也是。
- 方法:接口中的方法只能是:public abstract撒汉。 省略的話沟优,也是public abstract.
接口的本質(zhì)
接口就是
規(guī)范
,定義的是一組規(guī)則睬辐,體現(xiàn)了現(xiàn)實世界中“如果你是…則必須能…”的思想挠阁。如果你是天使,
則必須能飛溉委。如果你是汽車鹃唯,則必須能跑。如果你好人瓣喊,則必須干掉壞人坡慌;如果你是壞人,則必須欺負(fù)好人藻三。接口的本質(zhì)是契約洪橘,就像我們?nèi)碎g的法律一樣跪者。制定好后大家都遵守。
接口使用要點
子類通過 implements 來實現(xiàn)接口中的規(guī)范
接口不能創(chuàng)建實例熄求,但是可用于聲明引用變量類型渣玲。
一個類實現(xiàn)了接口,必須實現(xiàn)接口中所有的方法弟晚,并且這些方法只能是 public 的忘衍。
接口中只能包含靜態(tài)常量、抽象方法 卿城,不能有普通屬性枚钓、構(gòu)造方法、普通方法瑟押、靜態(tài)塊搀捷。
通過extends繼承父類,通過implements實現(xiàn)接口
接口的使用 : 通過實現(xiàn)類對象調(diào)用
具體實現(xiàn)類 : 重寫所有的抽象方法 + 按需新增
抽象實現(xiàn)類 : 按需重寫 + 按需 新增
如果一個類需要同時繼承父類實現(xiàn)接口,要求先繼承后實現(xiàn)
類與接口之間,只能是類實現(xiàn)接口,可以多實現(xiàn)
類與類之間,只能單繼承
接口與接口之間,可以多繼承
public class Test { public static void main(String[] args) { Volant volant = new Angel(); volant.fly(); System.out.println(Volant.FLY_HIGHT); } } interface Volant { int FLY_HIGHT = 100; // 總是:public static final void fly(); //總是:public abstract void fly2(); } interface Honest { void helpOther(); } class Angel implements Volant, Honest{ public void fly() { System.out.println("我是天使,飛起來啦多望!"); } public void helpOther() { System.out.println("扶老奶奶過馬路嫩舟!"); } } class GoodMan implements Honest { public void helpOther() { System.out.println("扶老奶奶過馬路!"); } } class BirdMan implements Volant { public void fly() { System.out.println("我是鳥人怀偷,正在飛家厌!"); } } class Bird implements Volant { public void fly() { System.out.println("正在飛!"); } } class Plane implements Volant { public void fly() { System.out.println("正在飛枢纠!"); } } class Satellite implements Volant { public void fly() { System.out.println("正在飛像街!"); } } class Missile implements Volant { public void fly() { System.out.println("正在飛!"); } }
注
Java 8發(fā)布以后晋渺,可以給接口添加新方法,但是脓斩,接口仍然可以和它的實現(xiàn)類保持兼容木西。這非常重要,因為你開發(fā)的類庫可能正在被多個開發(fā)者廣泛的使用著随静。而Java8之前八千,在類庫中發(fā)布了一個接口以后,如果在接口中添加一個新方法燎猛,那些實現(xiàn)了這個接口的應(yīng)用使用新版本的接口就會有崩潰的危險恋捆。(java8中也不能直接完全避免這個問題)
接口中被實現(xiàn)的方法叫做default方法,用關(guān)鍵字default作為修飾符來標(biāo)識重绷。當(dāng)一個類實現(xiàn)一個接口的時候沸停,它可以實現(xiàn)已經(jīng)在接口中被實現(xiàn)過的方法,但這不是必須的昭卓。這個類會繼承default方法愤钾。這就是為什么當(dāng)接口發(fā)生改變的時候瘟滨,實現(xiàn)類不需要做改動的原因。
在java8中的接口中不僅增加了默認(rèn)方法能颁,還增加了靜態(tài)方法杂瘸。
定義一個或者更多個靜態(tài)方法。類似于類中的靜態(tài)方法伙菊,接口定義的靜態(tài)方法可以獨立于任何對象
調(diào)用败玉。所以,在調(diào)用靜態(tài)方法時镜硕,不需要實現(xiàn)接口绒怨,也不需要接口的實例,也就是說和調(diào)用類的靜
態(tài)方法的方式類似谦疾。語法如:接口名字.靜態(tài)方法名
南蹂。實現(xiàn)接口的類或者子接口不會繼承接口中的靜態(tài)方法。static不能和default同時使用念恍。在java8中
很多接口中都增加了靜態(tài)方法
總結(jié)
jdk8接口新增 :
- 靜態(tài)方法
通過接口名.調(diào)用
- 默認(rèn)方法 : 通過default修飾
通過實現(xiàn)類對象調(diào)用
jdk9接口新增 :
1.私有方法 : 被private修飾的方法
只能在默認(rèn)方法中調(diào)用
接口是可以多繼承的六剥,通過逗號分割
繼承與實現(xiàn)區(qū)別
一個類可以單繼承一個父類,可以多實現(xiàn)多個接口
繼承 : 一個類如果繼承了一個父類,繼承了父類的成員,有權(quán)使用父類的成員,拿過來直接使用,如果存在個別情況不滿意,可以在子類中重寫
實現(xiàn) : 一個實現(xiàn)類如果實現(xiàn)了一個接口,擁有了接口帶來的功能,需要先在實現(xiàn)類中重寫抽象方法,重寫之后再使用
面向接口編程
面向接口編程是面向?qū)ο缶幊痰囊徊糠?/p>
為什么需要面向接口編程? 軟件設(shè)計中最難處理的就是需求的復(fù)雜變化,需求的變化更多的體現(xiàn)在
具體實現(xiàn)上峰伙。我們的編程如果圍繞具體實現(xiàn)來展開就會陷入”復(fù)雜變化”的汪洋大海中疗疟,軟件也就不
能最終實現(xiàn)。我們必須圍繞某種穩(wěn)定的東西開展瞳氓,才能以靜制動策彤,實現(xiàn)規(guī)范的高質(zhì)量的項目。接口
就是編程中最穩(wěn)定的東東匣摘!面向接口編程可以讓我把握住真正核心的東西店诗,使實現(xiàn)復(fù)雜的多變的需
求成為可能。通過面向接口編程音榜,而不是面向?qū)崿F(xiàn)類編程庞瘸,可以大大降低程序模塊間的耦合性,提高整個系統(tǒng)的可擴
展性和和可維護(hù)性赠叼。面向接口編程的概念比接口本身的概念要大得多擦囊。設(shè)計難,在你沒有寫實現(xiàn)時就要想好接口嘴办,接口一變就亂套了瞬场,設(shè)計要比實現(xiàn)難!
內(nèi)部類(innerclasses)
一般情況涧郊,我們把類定義成獨立的單元贯被。有些情況下,我們把一個類放在另一個類的內(nèi)部定義,稱為內(nèi)部類刃榨。形式如下:
public class Outter{ // 外部類 class Inner{ // 成員內(nèi)部類 } public void test(){ class Inner1{ // 局部內(nèi)部類 } } }
外部類的修飾符: public , default
內(nèi)部類的作用
在Java中弹砚,可以將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類枢希。
- 成員內(nèi)部類
- 局部內(nèi)部類
- 匿名內(nèi)部類
- 靜態(tài)內(nèi)部類
- 內(nèi)部類可以很好的實現(xiàn)細(xì)節(jié)隱藏桌吃。 一般的非內(nèi)部類,是不允許有 private 與 protected 權(quán)限的苞轿,
但內(nèi)部類可以茅诱。- 內(nèi)部類擁有外圍類的所有元素的訪問權(quán)限,利用這個特性可以實現(xiàn)java中的多繼承搬卒。
- 內(nèi)部類仍然是一個獨立的類瑟俭,在編譯之后內(nèi)部類會被編譯成獨立的.class文件,但是前面冠以外部
類的類名和$符號 契邀。- 內(nèi)部類聲明成靜態(tài)的摆寄,就不能隨便的訪問外部類的成員變量了,此時內(nèi)部類只能訪問外部類的靜態(tài)
成員變量坯门。- 可以避免修改接口而實現(xiàn)同一個類中兩種同名方法的調(diào)用
成員內(nèi)部類
成員內(nèi)部類可以訪問外部類的所有成員變量和方法(無論靜態(tài)微饥、非靜態(tài)、私有古戴、非私有)欠橘,自身沒有靜態(tài)成員。
內(nèi)部類其實嚴(yán)重破壞了良好的代碼結(jié)構(gòu)现恼,但為什么還要使用內(nèi)部類呢肃续?
內(nèi)部類可以隨意使用外部類的成員變量(包括private)而不用生成外部類的對象,這也是內(nèi)部類的唯一優(yōu)點
雖然成員內(nèi)部類可以無條件地訪問外部類的成員叉袍,而外部類想訪問成員內(nèi)部類的成員卻不是這么隨心所欲了始锚。
在外部類中如果要訪問成員內(nèi)部類的成員,必須先創(chuàng)建一個成員內(nèi)部類的對象畦韭,再通過指向這個對象的引用來訪問疼蛾。
創(chuàng)建內(nèi)部類實例
public class Test {
public static void main(String[] args) {
//第一種方式:
Outter outter = new Outter();
//必須通過Outter對象來創(chuàng)建
Outter.Inner inner1 = outter.new Inner();
//第二種方式:
Outter.Inner inner2 = outter.getInnerInstance();
}
}
class Outter {
private Inner inner = null;
public Outter() {
}
public Inner getInnerInstance() {
if(inner == null)
inner = new Inner();
return inner;
}
class Inner {
public Inner() {
}
}
}
成員內(nèi)部類私有化
如果一個內(nèi)部類只希望被外部類中的方法操作,那么可以使用private 聲明內(nèi)部類艺配,此時我們必須在
Out 類里面生成 In 類的對象進(jìn)行操作,而無法再使用 Out.In in = new Out().new In() 生成內(nèi)部類
的對象也就是說衍慎,此時的內(nèi)部類只有外部類可控制转唉;如同是,我的心臟只能由我的身體控制稳捆,其他人無
法直接訪問它赠法。
局部內(nèi)部類
局部內(nèi)部類是定義在一個方法或者一個作用域里面的類
它和成員內(nèi)部類的區(qū)別在于局部內(nèi)部類的訪問僅限于方法內(nèi)或者該作用域內(nèi)。
只能訪問方法中定義的 final 類型的局部變量(初始化之后便不能更改), final 可以不寫,編譯之后會變?yōu)閒inal砖织。
只能在方法內(nèi)部使用款侵。
void test(){ int a = 10; class Inner{ void test(){ System.out.println(a); } } Inner inner = new Inner(); inner.test(); }
靜態(tài)內(nèi)部類
當(dāng)使用內(nèi)部類只是為了把一個類隱藏在另外一個類的內(nèi)部,并不需要內(nèi)部類引用外圍對象侧纯,可以將內(nèi)部
類聲明為 static 新锈。如果用 static 將內(nèi)部類靜態(tài)化,那么內(nèi)部類就只能訪問外部類的靜態(tài)成員變量眶熬,
不能直接訪問外部類的實例變量妹笆、實例方法烈炭,只有通過對象引用才能訪問姐扮。其次,因為內(nèi)部類被靜態(tài)化马澈,因此 Out.In 可以當(dāng)做一個整體看贸弥,可以直接new 出內(nèi)部類的對象(靜態(tài)
內(nèi)部類不通過外部類實例進(jìn)行創(chuàng)建對象)生成靜態(tài)內(nèi)部類對象的方式為:
public class Test { public static void main(String[] args) { Outter.Inner inner = new Outter.Inner(); } } class Outter { public Outter() { } static class Inner { public Inner() { } } }
匿名內(nèi)部類
定義類的最終目的是創(chuàng)建一個類的實例窟坐,但是如果某個類以及它的實例只是用一次,則可以將類的定義與類的創(chuàng)建绵疲,放到與一起完成哲鸳,或者說在定義類的同時就創(chuàng)建一個類 , 以這種方法定義的沒有名字的類成為匿名內(nèi)部類。
用于只創(chuàng)建這個類的一個對象的場合(不必命名)最岗,通常是作為方法的參數(shù)帕胆,隱式地繼承了一個父類或者實現(xiàn)了一個接口“愣桑或直接使用接口引用指向匿名子類對象懒豹。
Outter o = new Outter(){};
①匿名內(nèi)部類可以繼承一個類或?qū)崿F(xiàn)一個接口,這里的 ClassOrInterfaceName 是匿名內(nèi)部類所繼承的
類名或?qū)崿F(xiàn)的接口名驯用。但匿名內(nèi)部類不能同時實現(xiàn)一個接口和繼承一個類脸秽,也不能實現(xiàn)多個接口。如果
實現(xiàn)了一個接口蝴乔,該類是 Object 類的直接子類记餐,匿名類繼承一個類或?qū)崿F(xiàn)一個接口,不需要 extends
和 implements 關(guān)鍵字薇正。②由于匿名內(nèi)部類沒有名稱片酝,所以類體中不能定義構(gòu)造方法,由于不知道類名也不能使用關(guān)鍵字來創(chuàng)建
該類的實例挖腰。實際上匿名內(nèi)部類的定義雕沿、構(gòu)造、和第一次使用都發(fā)生在同樣一個地方猴仑。此外审轮,以下是一
個表達(dá)式,返回的是一個對象的引用,所以可以直接使用或?qū)⑵鋸?fù)制給一個對象變量,如:TypeName obj=new Name(){ /*此處為類體*/ }
同樣疾渣,也可以將構(gòu)造的對象作為調(diào)用的參數(shù)篡诽。例:
someMethod(new Name(){ /*此處為類體*/ });
長達(dá)兩周的面向?qū)ο蠼K于結(jié)束了
無論你身處何時何地,永遠(yuǎn)不要放棄自己的夢想榴捡。即使你的夢想看起來很遙遠(yuǎn)杈女,你仍然應(yīng)該朝著它前進(jìn)。因為只有在追求夢想的過程中薄疚,我們才能找到意義和價值碧信。