摘要:非內(nèi)部類通過一個特殊的鏈接到其外圍類的對象,而類型的內(nèi)部類無此引用。
用thinkpad打字確實很爽??!
Thinking in java系列博文目錄:
Java編程思想學(xué)習(xí)錄(連載之:一切都是對象)
Java編程思想學(xué)習(xí)錄(連載之:初始化與清理)
Java編程思想學(xué)習(xí)錄(連載之:內(nèi)部類)
Java編程思想學(xué)習(xí)錄(連載之:異常)
注: 本文首發(fā)于 My 公眾號 CodeSheep ,可 長按 或 掃描 下面的 小心心 來訂閱 ↓ ↓ ↓內(nèi)部類基本概念
可將一個類的定義置于另一個類定義的內(nèi)部
內(nèi)部類允許將邏輯相關(guān)的類組織在一起,并控制位于內(nèi)部的類的可見性
甚至可將內(nèi)部類定義于一個方法或者任意作用域內(nèi)!
當然,內(nèi)部類 ≠ 組合
內(nèi)部類擁有其外圍類 所有元素的 訪問權(quán)
更有甚,嵌套多層的內(nèi)部類能透明地訪問所有它所嵌入的外圍類的所有成員
一個典型的例子:利用 Java內(nèi)部類 實現(xiàn)的 迭代器模式
// 接口 ------------------------------------------------------------- public interface Selector { boolean end(); Object current(); void next(); } // 外部類(集合類) + 內(nèi)部類(迭代器類) ------------------------------------------------------------- public class Sequence { // 外部類(代表一個集合類) private Object[] items; private int next = 0; public Sequence( int size ) { items = new Object[size]; } public void add( Object x ) { if( next < items.length ) items[next++] = x; } // 迭代器類:實現(xiàn)了 Selector接口的 內(nèi)部類 private class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if( i.this 與 .new 的使用場景 .this用于在內(nèi)部類中生成對其外部類對象的引用之時,舉例:
public class DotThis { void f() { print("DotThis.f()"); } public class Inner { // 內(nèi)部類 public DotThis outer() { // 返回外部類對象的引用 return DotThis.this; // 若直接返回this,那指的便是內(nèi)部類自身 } } public Inner inner() { return new Inner(); } public static void main( String[] args ) { DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); // 輸出 DotThis.f() } }.new用于直接創(chuàng)建內(nèi)部類的對象之時,距離:
public class DotNew { public class Inner { } // 空內(nèi)部類 public static void main( String[] args ) { DotNew dn = new DotNew(); DotNew.Inner dni = dn.new Inner(); //注意此處必須使用外部類的對象,而不能直接 DotNew.Inner dni = new DotNew.Inner() } }嵌套類(static類型的內(nèi)部類)嵌套類是無需依賴其外部類的對象的。非static內(nèi)部類通過一個特殊的this鏈接到其外圍類的對象,而static類型的內(nèi)部類無此this引用。
接口與內(nèi)部類有著很有趣的關(guān)系:
放到接口中的任何類自動都是public且static,即接口中的任何類都是嵌套類,我們甚至可以在接口的內(nèi)部類中去實現(xiàn)其外圍接口,舉例:public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { // 類Test默認static,所以是嵌套類 public void howdy() { print("Howdy!"); } public static void main( String[] args ) { new Test().howdy(); } } }在 方法 和 作用域 內(nèi)的內(nèi)部類可以稱這類為 局部內(nèi)部類!
方法中定義的內(nèi)部類只能在方法內(nèi)被使用,方法之外不可訪問,舉例:
public class Parcel { // parcel是“包裹”之意 public Destination destination( String s ) { class PDestination implements Destination { // 方法中定義的內(nèi)部類 private String label; private PDestination( String whereTo ) { label = whereTo; } public String readLabel() { return label; } } return new PDestination( s ); // 只有在方法中才能訪問內(nèi)部類PDestination } public static void main( String[] args ) { Parcel p = new Parcel(); Destination d = p.destination( "Hello" ); ... } }更進一步,可在任意作用域內(nèi)定義內(nèi)部類,舉例:
public class Parcel { private void internalTracking( boolean b ) { if( b ) { // 局部作用域中定義了內(nèi)部類,作用域之外不可訪問! class TrackingSlip { private String id; TrackingSlip( String s ) { id = s; } String getSlip() { return id; } } } } public void track() { interTracking( true ); } public static void main( String[] args ) { Parcel p = new Parcel(); p.track(); } }匿名內(nèi)部類直觀上看,這種內(nèi)部類沒有“名字”,舉例:
public class Parcel { public Contents contents() { return new Contents() { // 此即匿名內(nèi)部類!??! private int i = 11; public int value() { return i; } }; // ?。?!注意這里必須要加分號?。?! } public static void main( String[] args ) { Parcel p = new Parcel(); Contents c = p.contents(); } }若想將外部的參數(shù)傳到匿名內(nèi)部類中(典型的如將外部參數(shù)用于對匿名內(nèi)部類中的定義字段進行初始化時)使用的話,該參數(shù)必須final,舉例:
public class Parcel { public Destination destination( final String s ) { // final必須! return new Destination() { private String label = s; public String readLabel() { return label; } }; // 分號必須! } public static void mian( String[] args ) { Parcel p = new Parcel(); Destination d = p.destination("Hello"); } }匿名內(nèi)部類中不可能有命名的顯式構(gòu)造器,此時只能使用實例初始化的方式來模仿,舉例(當然下面這個例子還反映了匿名內(nèi)部類如何參與繼承):
// 基類 --------------------------------------------- abstact class Base() { public Base( int i ) { print( "Base ctor, i = " + i ); } public abstract void f(); } //主類(其中包含了繼承上面Base的派生匿名內(nèi)部類?。?---------------------------------------------- public class AnonymousConstructor { public static Base getBase( int i ) { // 該處參數(shù)無需final,因為并未在下面的內(nèi)部類中直接使用! return new Base(i){ // 匿名內(nèi)部類 { // 實例初始化語法?。?! print("Inside instance initializer"); } public void f() { print( "In anonymous f()" ); } }; // 分號必須! } public static void main( String[] args ) { Base base = getBase(47); base.f(); } } // 輸出 ------------------------------------------ Base ctor, i = 47 // 先基類 Inside instance initializer // 再打印派生類 In anonymous f()匿名內(nèi)部類 + 工廠模式 = 更加簡潔易懂:
// Service接口 --------------------------------------------------- interface Service { void method1(); void method2(); } // ServiceFactory接口 --------------------------------------------------- interface ServiceFactory { Service getService(); } // Service接口的實現(xiàn) --------------------------------------------------- class Implementation1 implements Service { private Implementation1() {} // 構(gòu)造函數(shù)私有 public void method1() { print("Implementation1 method1"); } public void method2() { print("Implementation1 method2"); } public static ServiceFactory factory = new ServiceFactory() { public Service getService() { return new Implementation1(); } }; // 分號必須?。?! } class Implementation2 implements Service { private Implementation2() {} public void method1() { print("Implementation2 method1"); } public void method2() { print("Implementation2 method2"); } public static ServiceFactory factory = new ServiceFactory() { public Service getService() { return new Implementation2(); } }; // 分號必須?。?! } // 客戶端代碼 ---------------------------------------------------- public class Factories { public static void serviceConsumer( ServiceFactory fact ) { Service s = fact.getService(); s.method1(); s.method2(); } public static void main( String[] args ) { serviceComsumer( Implementation1.factory ); serviceComsumer( Implementation2.factory ); } }總結(jié):為什么需要內(nèi)部類內(nèi)部類可以獨立地繼承自一個接口或者類而無需關(guān)注其外圍類的實現(xiàn),這使得擴展類或者接口更加靈活,控制的粒度也可以更細!
注意Java中還有一個細節(jié):雖然Java中一個接口可以繼承多個接口,但是一個類是不能繼承多個類的!要想完成該特性,此時除了使用內(nèi)部類來“擴充多重繼承機制”,你可能別無選擇,舉例:
class D { } // 普通類 abstract class E { } // 抽象類 class Z extend D { // 外圍類顯式地完成一部分繼承 E makeE() { return new E() { }; // 內(nèi)部類隱式地完成一部分繼承 } } public class MultiImplementation { static void takesD( D d ) { } static void takesE( E e ) { } public static void main( String[] args ) { Z z = new Z(); takesD( z ); takesE( z.makeE() ); } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68291.html
摘要:注本文首發(fā)于公眾號,可長按或掃描下面的小心心來訂閱關(guān)于構(gòu)造器與初始化無參構(gòu)造器默認構(gòu)造器自己未寫編譯器幫忙自動創(chuàng)建的若自行定義了構(gòu)造器無論參數(shù)有否,編譯器便停止默認創(chuàng)建動作類里的對象引用默認初始化為,基本類型初始化為構(gòu)造器也是類的靜態(tài)方法四 showImg(https://segmentfault.com/img/remote/1460000015723687); 注: 本文首發(fā)于 ...
摘要:系列博文目錄編程思想學(xué)習(xí)錄連載之一切都是對象編程思想學(xué)習(xí)錄連載之初始化與清理編程思想學(xué)習(xí)錄連載之內(nèi)部類編程思想學(xué)習(xí)錄連載之異常本篇文章將講述關(guān)于異常的相關(guān)知識注本文首發(fā)于公眾號,可長按或掃描下面的小心心來訂閱基本概念使用異常來提供一致性的錯 showImg(https://segmentfault.com/img/remote/1460000013228854); Thinking ...
摘要:前端技術(shù)棧還是非常龐大的,為了能夠借助已經(jīng)存在的輪子來造出一輛車,所以我選擇了進行實踐。狀態(tài)的管理的狀態(tài)管理依靠完成,用其來管理的所有組件狀態(tài)。私有云客戶端打造主頁面首先是主頁面,可以打開任何一個云主機系統(tǒng)的頁面看,基本類似。 showImg(https://segmentfault.com/img/remote/1460000013930354); 【利用K8S技術(shù)棧打造個人私有...
摘要:前端技術(shù)棧還是非常龐大的,為了能夠借助已經(jīng)存在的輪子來造出一輛車,所以我選擇了進行實踐。狀態(tài)的管理的狀態(tài)管理依靠完成,用其來管理的所有組件狀態(tài)。私有云客戶端打造主頁面首先是主頁面,可以打開任何一個云主機系統(tǒng)的頁面看,基本類似。 showImg(https://segmentfault.com/img/remote/1460000013930354); 【利用K8S技術(shù)棧打造個人私有...
摘要:我稱之為輕量級函數(shù)式編程。序眾所周知,我是一個函數(shù)式編程迷。函數(shù)式編程有很多種定義。本書是你開啟函數(shù)式編程旅途的絕佳起點。事實上,已經(jīng)有很多從頭到尾正確的方式介紹函數(shù)式編程的書了。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson?。 禮ou-Dont-Know-JS》作者 譯者團隊(排名不分先后):阿希、blueken、brucecham、...
閱讀 3125·2023-04-25 16:50
閱讀 924·2021-11-25 09:43
閱讀 3537·2021-09-26 10:11
閱讀 2532·2019-08-26 13:28
閱讀 2544·2019-08-26 13:23
閱讀 2440·2019-08-26 11:53
閱讀 3581·2019-08-23 18:19
閱讀 3003·2019-08-23 16:27