4.1 內(nèi)部類概述
????????定義在其他類內(nèi)部的類被稱為內(nèi)部類,包含內(nèi)部類的類也被稱為外部類。
? ? 內(nèi)部類有如下作用:
? ? ? ? - 內(nèi)部類提供了更好的封裝,可以把內(nèi)部類隱藏在外部類之內(nèi),不允許同一個包中的其他類訪問該類。
? ? ? ? - 內(nèi)部類成員可以直接訪問外部類的私有數(shù)據(jù),因為內(nèi)部類被當成其外部類成員,而同一個類的成員可以互相訪問。但外部類不能訪問內(nèi)部類的實現(xiàn)細節(jié)。
? ? ? ? - 匿名內(nèi)部類適用于創(chuàng)建那些僅需要一次使用的類。
? ??內(nèi)部類與外部類的區(qū)別:
? ? ? ? - 內(nèi)部類比外部類可以多使用三個修飾符:private、protected、static。
? ? ? ? - 非靜態(tài)內(nèi)部類不能擁有靜態(tài)成員。
? ? ? ? 成員內(nèi)部類是一種與成員變量、方法、構造器、初始化塊相似的類成員;局部內(nèi)部類和匿名內(nèi)部類則不是類成員。
? ? ? ? 成員內(nèi)部類分為兩種:非靜態(tài)內(nèi)部類和靜態(tài)內(nèi)部類。成員內(nèi)部類的class文件總是這種格式:OuterClass$InnerClass.class。
4.2 非靜態(tài)內(nèi)部類
? ? ? ? 非靜態(tài)內(nèi)部類的成員可以直接訪問外部類的private成員。非靜態(tài)內(nèi)部類對象里,保存了一個它所寄生的外部類對象的引用。
? ? ? ? 如果外部類需要訪問非靜態(tài)內(nèi)部類的成員,則必須通過非靜態(tài)內(nèi)部類對象來訪問其實例成員。
? ? ? ? 如果外部類成員變量、內(nèi)部類成員變量和內(nèi)部類方法的局部變量同名,則可通過使用外部類類名.this、this作為限定進行區(qū)分。
? ? ? ? 根據(jù)靜態(tài)成員不能訪問非靜態(tài)成員的規(guī)則,外部類的靜態(tài)方法、靜態(tài)代碼塊不能訪問非靜態(tài)內(nèi)部類,包括不能使用非靜態(tài)內(nèi)部類定義變量、創(chuàng)建實例等。
? ? ? ? 非靜態(tài)內(nèi)部類里不能有靜態(tài)方法、靜態(tài)成員變量、靜態(tài)初始化塊。
4.3 靜態(tài)內(nèi)部類
? ? ? ? 如果使用static來修飾一個內(nèi)部類,則此內(nèi)部類屬于外部類本身,而不屬于外部類的某個對象。
? ? ? ? 靜態(tài)內(nèi)部類可以包含靜態(tài)成員,也可以包含非靜態(tài)成員。靜態(tài)內(nèi)部類不能訪問外部類的實例成員,只能訪問外部類的類成員。即使是靜態(tài)內(nèi)部類的實例方法也不能訪問外部類的實例成員,只能訪問外部類的靜態(tài)成員。因為靜態(tài)內(nèi)部類沒有外部類對象的this引用。
????????外部類的所有方法、所有初始化塊可以使用靜態(tài)內(nèi)部類定義變量、創(chuàng)建對象。但外部類依然不能直接訪問靜態(tài)內(nèi)部類的成員。
? ? ? ? 接口中可以定義靜態(tài)內(nèi)部類。
4.4 使用內(nèi)部類
? ? 在外部類內(nèi)部使用內(nèi)部類:
? ? ? ? 在外部類內(nèi)部使用內(nèi)部類時,與使用普通類的方式?jīng)]有區(qū)別。但外部類的靜態(tài)成員不能使用非靜態(tài)內(nèi)部類。
? ? 在外部類以外使用非靜態(tài)內(nèi)部類:
? ? ? ? 此時非靜態(tài)內(nèi)部類不能用private修飾,否則無法再外部類以外使用。使用其他三種訪問控制修飾符修飾的內(nèi)部類,與普通類的使用規(guī)則相同。
? ? ? ? 非靜態(tài)內(nèi)部類的對象和非靜態(tài)內(nèi)部類子類的對象都必須持有指向外部類對象的引用,區(qū)別是創(chuàng)建兩種對象時傳入外部類對象的方式不同:當創(chuàng)建非靜態(tài)內(nèi)部類的對象時,必須通過外部類對象來調(diào)用new關鍵字;當創(chuàng)建非靜態(tài)內(nèi)部類子類的對象時,必須使用外部類對象作為調(diào)用者來調(diào)用非靜態(tài)內(nèi)部類子類的構造器。
? ??在外部類以外定義內(nèi)部類引用變量的語法格式如下:
? ? ? ? OuterClass.InnerClass variable
??在外部類以外的地方創(chuàng)建非靜態(tài)內(nèi)部類實例的語法格式如下:
? ? ? ? OuterInstance.new InnerConstructor()
? ? 在外部類以外使用靜態(tài)內(nèi)部類:
? ? ? ? 因為靜態(tài)內(nèi)部類是外部類類相關的,因此創(chuàng)建靜態(tài)內(nèi)部類對象時無須創(chuàng)建外部類對象。
? ? ? ? 靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類聲明變量得方式相同,靜態(tài)內(nèi)部類創(chuàng)建對象的方式與普通類穿件對象的方式相同,但靜態(tài)內(nèi)部類前要加外部類前綴。
? ? 無法重寫內(nèi)部類:
內(nèi)部類的類名默認加了外部類的類名作為一個包命名空間,即使子類中寫一個和父類內(nèi)部類具有相同名字的內(nèi)部類,那么命名空間也不相同,所以無法重寫。
4.5 局部內(nèi)部類
????????如果把一個內(nèi)部類放在方法里定義(注意,不是像創(chuàng)建匿名內(nèi)部類那樣,而是在方法內(nèi)部。),則這個內(nèi)部類就是一個局部內(nèi)部類,局部內(nèi)部類僅在該方法里有效。
????????局部內(nèi)部類的class文件總是遵循如下命名方式:OuterClass$NInnerClass。數(shù)字N是為了區(qū)分同名的局部內(nèi)部類。
4.6 匿名內(nèi)部類
? ? ? ? 創(chuàng)建匿名內(nèi)部類是會立即創(chuàng)建一個該類的實例,這個類定義立即消失,匿名內(nèi)部類不能重復使用。匿名內(nèi)部類必須且只能實現(xiàn)一個父類,或只實現(xiàn)一個接口。
????匿名內(nèi)部類使用規(guī)則:
? ? ? ? - 匿名內(nèi)部類不能是抽象類,因為系統(tǒng)在創(chuàng)建匿名內(nèi)部類時,會立即創(chuàng)建匿名內(nèi)部類的對象。
? ? ? ? - 匿名內(nèi)部類不能定義構造器。由于匿名內(nèi)部類沒有類名,所以無法定義構造器,但匿名內(nèi)部類可以定義初始化塊。
? ? ? ? 當通過實現(xiàn)接口來創(chuàng)建匿名內(nèi)部類時,匿名內(nèi)部類不能顯示創(chuàng)建構造器,因此匿名內(nèi)部類只有一個隱式的無參構造器,所以new接口名后的括號里不能傳入?yún)?shù)值;但如果通過繼承父類來創(chuàng)建匿名內(nèi)部類時,匿名內(nèi)部類將擁有和父類相似的構造器。若父類構造器有參數(shù),則new類名后的括號里傳入的參數(shù)將直接賦值給父類的參數(shù)。
? ? ? ? Java7之前,要求局部內(nèi)部類、匿名內(nèi)部類訪問的局部變量必須使用final修飾;Java8以后,如果局部內(nèi)部類被匿名內(nèi)部類訪問,那么該局部變量會自動變成被final修飾的狀態(tài)。