Java中的內部類和靜態嵌套類之間的主要區別是什麼? 設計/實施在選擇其中一項方面是否起做用? 閉包
我認爲上述答案都不能向您說明在應用程序設計方面嵌套類和靜態嵌套類之間的真正區別: 函數
嵌套類能夠是非靜態的,也能夠是靜態的,而且在每種狀況下都是在另外一個類中定義的類 。 嵌套類僅應存在於封閉類中 ,若是嵌套類對其餘類(不單單是封閉類)有用,則應將其聲明爲頂級類。 this
非靜態嵌套類 :與包含類的封閉實例隱式關聯,這意味着能夠調用封閉實例的方法和訪問變量。 非靜態嵌套類的一種常見用法是定義Adapter類。 spa
靜態嵌套類 :沒法訪問封閉類實例並在其上調用方法,所以當嵌套類不須要訪問封閉類實例時,應使用此方法。 靜態嵌套類的常見用法是實現外部對象的組件。 設計
所以,從設計的角度來看,二者之間的主要區別是: 非靜態嵌套類能夠訪問容器類的實例,而靜態不能 。 code
首先沒有這樣的類稱爲靜態類。內部類使用的static修飾符(稱爲嵌套類)表示它是外部類的靜態成員,這意味着咱們能夠像其餘靜態成員同樣訪問它,而無需任何其餘外部類的實例。 (這本來是靜態的。) 對象
使用嵌套類和常規內部類的區別是: get
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
首先,咱們能夠實例化外部類,而後能夠訪問內部。 it
可是,若是Class爲Nested,則語法爲: io
OuterClass.InnerClass inner = new OuterClass.InnerClass();
它使用static語法做爲static關鍵字的常規實現。
簡單來講,咱們須要嵌套類,主要是由於Java不提供閉包。
嵌套類是在另外一個封閉類的主體內部定義的類。 它們有兩種類型-靜態和非靜態。
它們被視爲封閉類的成員,所以您能夠指定四個訪問說明符中的任何一個private, package, protected, public
。 頂級類沒有這種奢侈,只能將其聲明爲public
或package-private。
內部類(也稱爲非堆棧類)能夠訪問頂級類的其餘成員,即便它們被聲明爲私有的,而靜態嵌套類也不能訪問頂級類的其餘成員。
public class OuterClass { public static class Inner1 { } public class Inner2 { } }
Inner1
是咱們的靜態內部類,而Inner2
是咱們的非靜態內部類。 它們之間的主要區別在於,若是沒有Outer,就沒法建立Inner2
實例,由於能夠單首創建Inner1
對象。
您何時使用內部課程?
考慮一下Class A
和Class B
相關的狀況, Class B
須要訪問Class A
成員,而Class B
Class A
僅與Class A
有關。 內部類進入畫面。
要建立內部類的實例,您須要建立外部類的實例。
OuterClass outer = new OuterClass(); OuterClass.Inner2 inner = outer.new Inner2();
要麼
OuterClass.Inner2 inner = new OuterClass().new Inner2();
何時使用靜態內部類?
當您知道靜態內部類與封閉類/頂級類的實例沒有任何關係時,能夠定義它。 若是您的內部類不使用外部類的方法或字段,則只會浪費空間,所以請將其設爲靜態。
例如,要爲靜態嵌套類建立一個對象,請使用如下語法:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
靜態嵌套類的優勢是它不須要包含類/頂級類的對象便可工做。 這能夠幫助您減小應用程序在運行時建立的對象數量。
在建立實例的狀況下,非靜態內部類的實例是使用定義了外部類的對象的引用建立的。 這意味着它具備封閉實例。 可是,靜態內部類的實例是使用外部類的引用而不是外部類的對象的引用建立的。 這意味着它沒有封閉實例。
例如:
class A { class B { // static int x; not allowed here….. } static class C { static int x; // allowed here } } class Test { public static void main(String… str) { A o=new A(); A.B obj1 =o.new B();//need of inclosing instance A.C obj2 =new A.C(); // not need of reference of object of outer class…. } }
關於嵌套靜態類的使用有些微妙之處,在某些狀況下可能有用。
靜態屬性是在經過類的構造函數實例化該類以前實例化的,而嵌套的靜態類內部的靜態屬性彷佛直到該類的構造函數被調用以後才被實例化,或者至少在首次引用該屬性以後才實例化,即便它們被標記爲「最終」。
考慮如下示例:
public class C0 { static C0 instance = null; // Uncomment the following line and a null pointer exception will be // generated before anything gets printed. //public static final String outerItem = instance.makeString(98.6); public C0() { instance = this; } public String makeString(int i) { return ((new Integer(i)).toString()); } public String makeString(double d) { return ((new Double(d)).toString()); } public static final class nested { public static final String innerItem = instance.makeString(42); } static public void main(String[] argv) { System.out.println("start"); // Comment out this line and a null pointer exception will be // generated after "start" prints and before the following // try/catch block even gets entered. new C0(); try { System.out.println("retrieve item: " + nested.innerItem); } catch (Exception e) { System.out.println("failed to retrieve item: " + e.toString()); } System.out.println("finish"); } }
即便'nested'和'innerItem'都聲明爲'static final'。 直到實例化該類以後(或至少直到首次引用嵌套的靜態項目以後),nested.innerItem的設置纔會發生,您能夠經過註釋和取消註釋我所引用的行來親自看到,以上。 'outerItem'並不是如此。
至少這是我在Java 6.0中看到的。