面向对象回顾(构造函数、覆盖和重载、Query接口的list方法和iterate方法、面向对象的六原则一法则、反射、内部类)
1.?什么是構造函數?什么是構造函數重載?什么是復制構造函數?
當新對象被創建的時候,構造函數會被調用。
每一個類都有構造函數。
在程序員沒有給類提供構造函數的情況下,Java編譯器會為這個類創建一個默認的構造函數。
Java中構造函數重載和方法重載很相似。
- 可以為一個類創建多個構造函數。
- 每一個構造函數必須有它自己唯一的參數列表。
Java不支持像C++中那樣的復制構造函數,這個不同點是因為如果你不自己寫構造函數的情況下,Java不會創建默認的復制構造函數。
2.?方法覆蓋(Overriding)和方法重載(Overloading)是什么意思?
Java中的方法重載發生在同一個類里面兩個或者是多個方法的方法名相同但是參數不同的情況。
與此相對,方法覆蓋是說子類重新定義了父類的方法。
- 方法覆蓋必須有相同的方法名,參數列表和返回類型。
- 覆蓋者可能不會限制它所覆蓋的方法的訪問。
2.1?重載(Overload)和重寫(Override)的區別
方法的重載和重寫都是實現多態的方式,區別在于前者實現的是編譯時的多態性,而后者實現的是運行時的多態性。
重載發生在一個類中,同名的方法如果有不同的參數列表(參數類型不同、參數個數不同或者二者都不同)則視為重載;
重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求。
重載的方法能否根據返回類型進行區分?——不能
Overloaded的方法是可以改變返回值的類型。
3.?Query接口的list方法和iterate方法有什么區別?
3.1 緩存
- list()方法無法利用一級緩存和二級緩存(對緩存只寫不讀),它只能在開啟查詢緩存的前提下使用查詢緩存;
- iterate()方法可以充分利用緩存,如果目標數據只讀或者讀取頻繁,使用iterate()方法可以減少性能開銷。
3.2 N+1
- list()方法不會引起N+1查詢問題;
- 而iterate()方法可能引起N+1查詢問題。
4. 面向對象的"六原則一法則"
4.1 單一職責原則
一個類只做它該做的事情。
單一職責原則想表達的就是"高內聚"。
寫代碼最終極的原則只有六個字"高內聚、低耦合"
- 高內聚就是一個代碼模塊只完成一項功能。
- 在面向對象中,如果只讓一個類完成它該做的事,而不涉及與它無關的領域就是踐行了高內聚的原則,這個類就只有單一職責。
- 另一個是模塊化。
- 好的自行車是組裝車,從減震叉、剎車到變速器,所有的部件都是可以拆卸和重新組裝的,好的乒乓球拍也不是成品拍,一定是底板和膠皮可以拆分和自行組裝的;
- 一個好的軟件系統,它里面的每個功能模塊也應該是可以輕易的拿到其他系統中使用的,這樣才能實現軟件復用的目標。
4.2 開閉原則
軟件實體應當對擴展開放,對修改關閉。
在理想的狀態下,當我們需要為一個軟件系統增加新功能時,只需要從原來的系統派生出一些新類就可以,不需要修改原來的任何一行代碼。
要做到開閉有兩個要點:
如果不清楚如何封裝可變性,可以參考《設計模式精解》一書中對橋梁模式的講解的章節。
4.3 依賴倒轉原則
面向接口編程。
該原則說得直白和具體一些就是聲明方法的參數類型、方法的返回類型、變量的引用類型時,盡可能使用抽象類型而不用具體類型。
因為抽象類型可以被它的任何一個子類型所替代,請參考下面的里氏替換原則。
里氏替換原則
- 任何時候都可以用子類型替換掉父類型。
- 關于里氏替換原則的描述,Barbara Liskov女士的描述比這個要復雜得多,但簡單的說就是能用父類型的地方就一定能使用子類型。
- 里氏替換原則可以檢查繼承關系是否合理。
- 如果一個繼承關系違背了里氏替換原則,那么這個繼承關系一定是錯誤的,需要對代碼進行重構。
- 例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯誤的繼承關系,因為你很容易找到違反里氏替換原則的場景。
- 需要注意的是:子類一定是增加父類的能力而不是減少父類的能力,因為子類比父類的能力更多,把能力多的對象當成能力少的對象來用當然沒有任何問題。
4.4 接口隔離原則
接口要小而專,絕不能大而全。
臃腫的接口是對接口的污染,既然接口表示能力,那么一個接口只應該描述一種能力,接口也應該是高度內聚的。
例如,琴棋書畫就應該分別設計為四個接口,而不應設計成一個接口中的四個方法,因為如果設計成一個接口中的四個方法,那么這個接口很難用,畢竟琴棋書畫四樣都精通的人還是少數,而如果設計成四個接口,會幾項就實現幾個接口,這樣的話每個接口被復用的可能性是很高的。
Java中的接口代表能力、代表約定、代表角色,能否正確的使用接口一定是編程水平高低的重要標識。
4.5 合成聚合復用原則
優先使用聚合或合成關系復用代碼。
通過繼承來復用代碼是面向對象程序設計中被濫用得最多的東西,因為所有的教科書都無一例外的對繼承進行了鼓吹從而誤導了初學者。
類與類之間簡單的說有三種關系:
- Is-A關系——代表繼承
- Has-A關系——代表關聯
- Use-A關系——代表依賴
其中,關聯關系根據其關聯的強度又可以進一步劃分為:
- 關聯;
- 聚合;
- 合成
但說白了都是Has-A關系。
合成聚合復用原則想表達的是優先考慮Has-A關系而不是Is-A關系復用代碼
記住:任何時候都不要繼承工具類,工具是可以擁有并可以使用的,而不是拿來繼承的。
4.6 迪米特法則
迪米特法則又叫最少知識原則,一個對象應當對其他對象有盡可能少的了解。
再復雜的系統都可以為用戶提供一個簡單的門面。
Java Web開發中作為前端控制器的Servlet或Filter不就是一個門面嗎,瀏覽器對服務器的運作方式一無所知,但是通過前端控制器就能夠根據你的請求得到相應的服務。
調停者模式也可以舉一個簡單的例子來說明:
- 例如一臺計算機,CPU、內存、硬盤、顯卡、聲卡各種設備需要相互配合才能很好的工作,
- 但是如果這些東西都直接連接到一起,計算機的布線將異常復雜,
- 在這種情況下,主板作為一個調停者的身份出現,
- 它將各個設備連接在一起而不需要每個設備之間直接交換數據,這樣就減小了系統的耦合度和復雜度。
5. 反射
5.1 如何通過反射獲取和設置對象私有字段的值?
可以通過類對象的getDeclaredField()方法字段(Field)對象,然后再通過字段對象的setAccessible(true)將其設置為可以訪問,接下來就可以通過get/set方法來獲取/設置字段的值了。
下面的代碼實現了一個反射的工具類,其中的兩個靜態方法分別用于獲取和設置私有字段的值,字段可以是基本類型也可以是對象類型且支持多級對象操作,例如ReflectionUtil.get(dog, "owner.car.engine.id");可以獲得dog對象的主人的汽車的引擎的ID號。
import java.lang.reflect.Method; class MethodInvokeTest {public static void main(String[] args) throws Exception {String str = "hello";Method m = str.getClass().getMethod("toUpperCase");System.out.println(m.invoke(str)); // HELLO} }5.2?如何通過反射創建對象?
6.?內部類可以引用他包含類的成員嗎,如果可以,有沒有什么限制嗎?
一個內部類對象可以訪問創建它的外部類對象的內容。
內部類如果不是static的,那么它可以訪問創建它的外部類對象的所有屬性;
內部類如果是sattic的,即為nested class,那么它只可以訪問創建它的外部類對象的所有static屬性。
一般普通類只有public或package的訪問修飾,而內部類可以實現static,protected,private等訪問修飾。
當從外部類繼承的時候,內部類是不會被覆蓋的,它們是完全獨立的實體,每個都在自己的命名空間內,如果從內部類中明確地繼承,就可以覆蓋原來內部類的方法。?
6.1 Static Nested Class 和 Inner Class的不同
Static Nested Class是被聲明為靜態(static)的內部類,它可以不依賴于外部類實例被實例化。
而通常的內部類需要在外部類實例化后才能實例化。
Static-Nested Class 的成員, 既可以定義為靜態的(static), 也可以定義為動態的(instance)。
Nested Class的靜態成員(Method)只能對Outer Class的靜態成員(static memebr)進行操作(ACCESS), 而不能Access Outer Class的動態成員(instance member)。
而 Nested Class的動態成員(instance method) 卻可以 Access Outer Class的所有成員。 這個概念很重要,許多人對這個概念模糊.。
有一個普通的原則, 因為靜態方法(static method) 總是跟 CLASS 相關聯(bind CLASS),而動態方法( (instance method) 總是跟 instance object 相關聯。所以,靜態方法(static method)永遠不可以Access跟 object 相關的動態成員(instance member);反過來就可以, 一個CLASS的 instance object 可以 Access 這個 Class 的任何成員,包括靜態成員(static member)。
總結
以上是生活随笔為你收集整理的面向对象回顾(构造函数、覆盖和重载、Query接口的list方法和iterate方法、面向对象的六原则一法则、反射、内部类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基础回顾(Map、==/equals()
- 下一篇: 面向对象回顾(异常(try、catch、