[TOC]
面向?qū)ο螅∣OP)的程序是由對象組成的,每個對象包含對用戶公開的特定功能部分和隱藏的實現(xiàn)部分。
# 類
## 面向?qū)ο笕筇匦?封裝、繼承、多態(tài)
* 封裝隱藏了類的內(nèi)部實現(xiàn)機制,可以在不影響使用的情況下改變類的內(nèi)部結(jié)構(gòu),同時也保護了數(shù)據(jù)
* 繼承可以重用父類代碼,實現(xiàn)代碼復(fù)用和可擴展的效果
* 多態(tài)指對象的一個方法在調(diào)用時可以有多種狀態(tài),即父類引用可以持有子類對象
* 多態(tài)實現(xiàn)的兩種形式:基于繼承重寫、基于接口
* 多態(tài)存在的三個條件:繼承、重寫、父類引用持有子類對象
* 非靜態(tài)成員方法的調(diào)用:編譯看父類,運行看子類
* 多態(tài)優(yōu)點:不用創(chuàng)建一堆子類對象的引用;多態(tài)缺點:不能使用子類特有的成員屬性和成員方法
***注意點***
1、實現(xiàn)封裝的關(guān)鍵在于,絕對不能讓類中的方法直接地訪問其他類的實例域(對象中的數(shù)據(jù)),程序僅通過對象的方法與對象數(shù)據(jù)進行交互。
2、對象狀態(tài)的改變必須通過調(diào)用方法實現(xiàn)。
## 類之間的關(guān)系
依賴、聚合、繼承
* 依賴是最明顯、最常見的關(guān)系,如果一個類的方法操縱另一個類的對象,就說一個類依賴于另一個類
* 聚合指類A的對象包含類B的對象
## 自定義類
1、在一個Java源文件中,只能有一個公有類,但可以有任意數(shù)目的非公有類。
2、顯式參數(shù)指方法名后面括號中的數(shù)值,隱式參數(shù)指出現(xiàn)在方法名前的對象(在方法內(nèi)部可通過this來表示隱式參數(shù))。
3、靜態(tài)方法是一種不能向?qū)ο髮嵤┎僮鞯姆椒ǎ簿褪菦]有隱式參數(shù),不能操作對象,但可以訪問自身類中的靜態(tài)域。
4、按值調(diào)用表示方法接收的是調(diào)用者提供的值,按引用調(diào)用表示方法接收的是調(diào)用者提供的變量地址。
5、類設(shè)計技巧:
* 一定要保證數(shù)據(jù)私有
* 一定要對數(shù)據(jù)初始化,可以提供默認值,也可以在構(gòu)造器中設(shè)置默認值
* 不要在類中使用過多的基本類型
* 不是所有的域都需要獨立的域訪問器和域更改器
* 將職責(zé)過多的類進行分解
* 類名和方法名要能夠體現(xiàn)它們的職責(zé)
***重點***
* Java總是采用按值調(diào)用,方法得到的是參數(shù)值的一個拷貝,不能修改傳遞給它的任何參數(shù)變量的內(nèi)容
## 內(nèi)部類
將一個類的定義放在另一個類的定義內(nèi)部,這就是內(nèi)部類
內(nèi)部類分為成員內(nèi)部類、靜態(tài)內(nèi)部類、局部內(nèi)部類和匿名內(nèi)部類
### 成員內(nèi)部類
相當于外部類的一個成員。
```java
public class OuterClass {
private String mString = "a";
private void outerMethod() {
// 使用內(nèi)部類屬性或方法需要提供內(nèi)部類實例來實現(xiàn)
InnerClass innerClass = new InnerClass();
innerClass.innerMethod();
}
public class InnerClass {
// private static String mStaticString; ERROR!
public void innerMethod() {
// 使用外部類屬性
mString = "b";
// 使用外部類方法方法
outerMethod();
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.getInnerClass();
innerClass.innerMethod();
}
}
```
1、訪問規(guī)則
* 內(nèi)部類可以訪問外部類的所有屬性和方法,即使是私有的
* 外部類要訪問成員內(nèi)部類的屬性和方法,則需要通過成員內(nèi)部類的實例來實現(xiàn)
2、注意事項
* 成員內(nèi)部類中不能有任何 static 的屬性和方法
* 成員內(nèi)部類是依附于外部類的,只有先創(chuàng)建了外部類對象,才能夠創(chuàng)建成員內(nèi)部類,推薦使用 getxxx() 來獲取成員內(nèi)部類
* 成員內(nèi)部類中持有一個外部類的引用
### 靜態(tài)內(nèi)部類
靜態(tài)內(nèi)部類是一個碰巧被聲明在外部類中的普通類。
```java
public class OuterClass {
private static String sString;
private void outerMethod() {
// 外部類可訪問私有靜態(tài)類的屬性和方法
InnerClass innerClass = new InnerClass();
innerClass.innerMethod();
}
private static class InnerClass {
private void innerMethod() {
// 靜態(tài)內(nèi)部類只可以訪問外部類的靜態(tài)成員
sString = "a";
}
}
public static void main(String[] args) {
// 創(chuàng)建靜態(tài)內(nèi)部類對象不需要外部類對象
InnerClass innerClass = new InnerClass();
innerClass.innerMethod();
}
}
```
* 靜態(tài)內(nèi)部類不持有外部類的引用
* 和其他靜態(tài)成員一樣,被聲明為 private 時,只有外部類可訪問
* 靜態(tài)內(nèi)部類不能直接訪問外部類的任何非 static 成員變量和方法;卻可以直接訪問外部類的靜態(tài)成員,包括私有的
* 創(chuàng)建靜態(tài)內(nèi)部類時不需要創(chuàng)建外部類對象
* 聲明在接口中的內(nèi)部類自動成為 public 和 static
### 局部內(nèi)部類
```java
void setData() {
class ClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
// do click
}
}
mView.setOnClickListener(new ClickListener());
}
```
局部內(nèi)部類嵌套在方法和作用域內(nèi),像是方法里的一個局部變量一樣
* 局部內(nèi)部類對外界完全隱藏,即使是外部類也不能訪問它
* 局部內(nèi)部類可以訪問所在作用域的局部變量,但必須聲明為 final
* 有時候 final 的限制會不方便,可以使用一個長度為 1 的數(shù)組類替代
### 匿名內(nèi)部類
```java
void setData() {
mView.setOnClickListener(new View.OnClickListener() {
// do click
});
}
```
對局部內(nèi)部類的一種深化,只需要創(chuàng)建局部內(nèi)部類的一個對象時,就不需要命名了
1、定義
* 匿名內(nèi)部類語法格式為 `new SuperType(construction parameters){}`
* 父類后面括號中的參數(shù)會傳遞給父類的構(gòu)造器
* 匿名內(nèi)部類終歸還是個類。如果 SuperType 是一個接口,匿名類實現(xiàn)這個接口,并擴展自 Object 類;如果 SuperType 是一個類,則匿名類是該類的子類
2、注意
* 匿名內(nèi)部類屬于局部內(nèi)部類,局部內(nèi)部類的限制對于它同樣生效
* 匿名內(nèi)部類中不能定義構(gòu)造方法,因為它連名字都么有,但可以使用初始化語塊代替構(gòu)造方法
匿名內(nèi)部類初始化語塊示例:
```java
invite(new ArrayList<String>(){
{
add("Harry");
add("Tony");
}
};
);
```
### final關(guān)鍵字的理解
1、final的意思是【無法改變的】、【最終的】,可以修飾非抽象類、非抽象類的成員變量和成員方法
2、final類不能被繼承,沒有子類,其中的方法默認是final的
3、final方法不能被重寫,但可以被繼承(final不能用于修飾構(gòu)造方法)
4、final成員變量表示常量,只能被賦值一次,賦值后不再改變。
5、使用final聲明基礎(chǔ)數(shù)據(jù)類型時,數(shù)值恒定不變;使用final聲明對象引用時,引用的對象恒定不變,但對象的數(shù)據(jù)可變;使用final聲明數(shù)組類型時,引用的數(shù)組恒定不變,但數(shù)組內(nèi)的數(shù)據(jù)可變。
優(yōu)點:
1、編譯器遇到final方法時會轉(zhuǎn)入內(nèi)嵌機制,提高效率。
2、可以安全的在多線程環(huán)境下共享,不需要額外的同步開銷。
### 為什么匿名內(nèi)部類使用局部引用要用final
1、匿名內(nèi)部類屬于一種局部內(nèi)部類。
2、編譯后局部內(nèi)部類中會有一個成員變量,是對外部局部變量的引用的拷貝,在局部內(nèi)部類使用外部局部變量值時都是通過這個引用進行的。
3、為避免這個成員變量的值(引用的對象)被外部類的方法修改,導(dǎo)致內(nèi)部類在使用時得到的值不一樣,需要使用final讓該成員變量不可變。
4、局部變量位于方法內(nèi)部,在虛擬機的棧上,意味著這個變量無法進行共享,匿名內(nèi)部類無法直接訪問,只能通過值傳遞的方式,傳遞給匿名內(nèi)部類。
5、而類的成員變量在虛擬機的堆上,內(nèi)部類可以直接獲取這個變量,故類的成員變量不需要聲明為final內(nèi)部類就可訪問。
參考鏈接
[java提高篇(八)----詳解內(nèi)部類](https://www.cnblogs.com/chenssy/p/3388487.html)
# 對象
1、一個類的多個方法有相同的名字、不同的參數(shù),便產(chǎn)生了重載。編譯器通過用各個方法給出的參數(shù)類型與特定方法調(diào)用所使用的值類型進行匹配來挑選出相應(yīng)的方法,這個過程稱為重載解析。
2、完整的描述一個方法,需要指出方法名以及參數(shù)類型,這叫做方法的簽名。返回類型不是方法簽名的一部分,因此不能有兩個名字相同、參數(shù)類型也相同卻返回類型不同的方法。
# 繼承
## 繼承的 private 成員問題
關(guān)于子類是否可以繼承父類 private 成員問題,原來大家已經(jīng)討論很久了:
一種是子類不可以繼承父類的私有成員,私有成員是默認為 final 的,是不允許覆蓋的。但父類提供了 public、protected 方法訪問其私有成員時,子類或外部類可以通過 public、protected 方法訪問到。
另一種說法是子類繼承父類的所有成員,包括私有的。private,public,protected 和繼承沒有關(guān)系,他們對成員函數(shù)和變量的限制只是在成員的可見性上。因此私有成員變量和方法在子類中不可見,也就是擁有它,但不能使用它,必須通過父類的 public、protected 方法訪問。
個人比較傾向于第一種說法??梢钥聪聟⒖贾械腫《private 繼承之爭》](http://www.ithome.com.tw/voice/90371)一文,講解的比較不錯。
參考
[private 繼承之爭](http://www.ithome.com.tw/voice/90371)
[私有的成員能被子類繼承嗎?](http://www.blogjava.net/sitinspring/archive/2007/12/04/165288.html)
[Java 中子類是否會繼承父類中的 private 成員](http://woyixiaorenne.iteye.com/blog/2312477)
## 繼承的構(gòu)造方法問題
子類和父類的構(gòu)造方法不存在繼承關(guān)系,而是調(diào)用關(guān)系,存在以下原則:
* 子類構(gòu)造過程中必須調(diào)用父類的構(gòu)造方法
* 如果子類沒有顯示調(diào)用父類構(gòu)造方法,則系統(tǒng)默認調(diào)用父類的無參構(gòu)造方法(若系統(tǒng)無無參構(gòu)造方法,編譯報錯)
* 一個類未聲明任何構(gòu)造方法時,系統(tǒng)會默認生成一個無參構(gòu)造方法。當聲明了有參構(gòu)造方法時,就不會自動生成無參構(gòu)造方法了
靜態(tài)代碼塊、構(gòu)造代碼塊、構(gòu)造方法的執(zhí)行順序:
父類靜態(tài)代碼塊→子類靜態(tài)代碼塊→父類構(gòu)造代碼塊→父類構(gòu)造方法→子類構(gòu)造代碼塊→子類構(gòu)造方法
參考文檔:
[關(guān)于 Java 內(nèi)部類的小抄](http://blog.jrwang.me/2016/java-inner-class/)
- 導(dǎo)讀
- Java知識
- Java基本程序設(shè)計結(jié)構(gòu)
- 【基礎(chǔ)知識】Java基礎(chǔ)
- 【源碼分析】Okio
- 【源碼分析】深入理解i++和++i
- 【專題分析】JVM與GC
- 【面試清單】Java基本程序設(shè)計結(jié)構(gòu)
- 對象與類
- 【基礎(chǔ)知識】對象與類
- 【專題分析】Java類加載過程
- 【面試清單】對象與類
- 泛型
- 【基礎(chǔ)知識】泛型
- 【面試清單】泛型
- 集合
- 【基礎(chǔ)知識】集合
- 【源碼分析】SparseArray
- 【面試清單】集合
- 多線程
- 【基礎(chǔ)知識】多線程
- 【源碼分析】ThreadPoolExecutor源碼分析
- 【專題分析】volatile關(guān)鍵字
- 【面試清單】多線程
- Java新特性
- 【專題分析】Lambda表達式
- 【專題分析】注解
- 【面試清單】Java新特性
- Effective Java筆記
- Android知識
- Activity
- 【基礎(chǔ)知識】Activity
- 【專題分析】運行時權(quán)限
- 【專題分析】使用Intent打開三方應(yīng)用
- 【源碼分析】Activity的工作過程
- 【面試清單】Activity
- 架構(gòu)組件
- 【專題分析】MVC、MVP與MVVM
- 【專題分析】數(shù)據(jù)綁定
- 【面試清單】架構(gòu)組件
- 界面
- 【專題分析】自定義View
- 【專題分析】ImageView的ScaleType屬性
- 【專題分析】ConstraintLayout 使用
- 【專題分析】搞懂點九圖
- 【專題分析】Adapter
- 【源碼分析】LayoutInflater
- 【源碼分析】ViewStub
- 【源碼分析】View三大流程
- 【源碼分析】觸摸事件分發(fā)機制
- 【源碼分析】按鍵事件分發(fā)機制
- 【源碼分析】Android窗口機制
- 【面試清單】界面
- 動畫和過渡
- 【基礎(chǔ)知識】動畫和過渡
- 【面試清單】動畫和過渡
- 圖片和圖形
- 【專題分析】圖片加載
- 【面試清單】圖片和圖形
- 后臺任務(wù)
- 應(yīng)用數(shù)據(jù)和文件
- 基于網(wǎng)絡(luò)的內(nèi)容
- 多線程與多進程
- 【基礎(chǔ)知識】多線程與多進程
- 【源碼分析】Handler
- 【源碼分析】AsyncTask
- 【專題分析】Service
- 【源碼分析】Parcelable
- 【專題分析】Binder
- 【源碼分析】Messenger
- 【面試清單】多線程與多進程
- 應(yīng)用優(yōu)化
- 【專題分析】布局優(yōu)化
- 【專題分析】繪制優(yōu)化
- 【專題分析】內(nèi)存優(yōu)化
- 【專題分析】啟動優(yōu)化
- 【專題分析】電池優(yōu)化
- 【專題分析】包大小優(yōu)化
- 【面試清單】應(yīng)用優(yōu)化
- Android新特性
- 【專題分析】狀態(tài)欄、ActionBar和導(dǎo)航欄
- 【專題分析】應(yīng)用圖標、通知欄適配
- 【專題分析】Android新版本重要變更
- 【專題分析】唯一標識符的最佳做法
- 開源庫源碼分析
- 【源碼分析】BaseRecyclerViewAdapterHelper
- 【源碼分析】ButterKnife
- 【源碼分析】Dagger2
- 【源碼分析】EventBus3(一)
- 【源碼分析】EventBus3(二)
- 【源碼分析】Glide
- 【源碼分析】OkHttp
- 【源碼分析】Retrofit
- 其他知識
- Flutter
- 原生開發(fā)與跨平臺開發(fā)
- 整體歸納
- 狀態(tài)及狀態(tài)管理
- 零碎知識點
- 添加Flutter到現(xiàn)有應(yīng)用
- Git知識
- Git命令
- .gitignore文件
- 設(shè)計模式
- 創(chuàng)建型模式
- 結(jié)構(gòu)型模式
- 行為型模式
- RxJava
- 基礎(chǔ)
- Linux知識
- 環(huán)境變量
- Linux命令
- ADB命令
- 算法
- 常見數(shù)據(jù)結(jié)構(gòu)及實現(xiàn)
- 數(shù)組
- 排序算法
- 鏈表
- 二叉樹
- 棧和隊列
- 算法時間復(fù)雜度
- 常見算法思想
- 其他技術(shù)
- 正則表達式
- 編碼格式
- HTTP與HTTPS
- 【面試清單】其他知識
- 開發(fā)歸納
- Android零碎問題
- 其他零碎問題
- 開發(fā)思路
