<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                **一、接口** - 接口的理解 ?? Java接口是一系列方法的聲明,是一些方法特征的集合,一個接口只有方法的特征沒有方法的實現; ?? 也就是說,接口自身自提供方法的基本聲明,而不提供方法體;接口中聲明的方法只能被實現該接口的子類所具體實現。 ?? 接口是Java中另一種非常重要的結構。因為Java不支持多繼承,某種程度來說這也造成了一定的局限性。 ?? 所以接口允許多實現的特點彌補了類不能多繼承的缺點。通常通過繼承和接口的雙重設計,可以既保持類的數據安全也變相實現了多繼承。 - 接口的特點 1. 使用關鍵字"interface"聲明一個接口;使用關鍵字"implements"聲明一個類實現一個接口。 1. 與類的權限限制相同,接口的也只能被聲明為“public”或默認修飾符。 1. 接口當中聲明的變量被自動的設置為public、static、final,也就是說在接口聲明的變量實際都會被隱式的提升為"公有的靜態常量" 1. 接口中聲明的方法都是抽象的,并且都被自動的設置為public。 1. 接口自身不能被構造實例化,但可以通過實現該接口的類進行實例化。 1. 實現接口的類如果不是抽象類,那么該類就必須對接口中的方法進行實現。 1. 接口與接口之間也可以實現繼承關系。子接口除擁有父接口的所有方法聲明外,還可以定義新的方法聲明。 ~~~ package com.tsr.j2seoverstudy.interface_demo; //訪問修飾符只能為public或默認訪問修飾符 public interface InterfaceDemo { // 會被隱式的提升為:public static final int VAR = 50; int VAR = 50; // public void methodDemo(); void methodDemo();//方法必須是抽象的 } class Test implements InterfaceDemo{ public static void main(String[] args) { InterfaceDemo in = new InterfaceDemo();//compile exception InterfaceDemo in = new Test();//但可以聲明接口類型的變量,并通過實現該接口的類來進行實例化 } @Override public void methodDemo() { } }?? ~~~ ? 根據接口的特點,實際上我們可以看到:接口實際上更像是在聲明一種規范,相當于實現定義了程序的一種框架。例如,作為一種遙控汽車的設計者。你可能需要提供一些規范給這些遙控汽車的生產廠商們,讓他們按照你的設計規范來生產遙控汽車。 ~~~ package com.tsr.j2seoverstudy.interface_demo; public interface Moveable { void turnLeft(); void turnRight(); void stop(); } ~~~ ?? 這是你提供的讓玩具汽車具備可移動性(moveable)的接口,生產廠商必須按照該接口的規范進行實現,才能然小汽車成功的move起來。 - 接口與抽象類的區別 1. 一個類可以實現多個接口,但只能繼承一個抽象類。 1. 抽象類中可以存在非抽象方法,但接口中聲明的方法必須是抽象的。 1. 抽象類中的方法可以是任何的訪問權限,但接口中的方法都是public權限的。 1. 抽象類中可以存在自己定義的任何類型的實例域(變量等),但接口中的域都是公有、靜態、最終的。 ?? 而抽象類和接口最大的相同之處,可能就在于:都是對其體系中的對象,不斷的進行向上抽取而來的共有特性。它們都可以用于多態的實現。 **二、內部類** 1、什么是內部類? 顧名思義,內部類就指定義在另一個類的內部當中的類。我們知道一個Java所編寫的基本體現形式就是一個類,而一個類的結構通常是由域(靜態域、實例域)和方法構成的。而有時候一個類中還有另一種構成部分,就是內部類。 2、為什么使用內部類? 關于這點,《Java2學習指南》中這樣說:你是一個OO程序猿,因此知道為了代碼的重用性和靈活性(可擴展性),需要將類保持足夠的專用性。也就是說,一個類只應該具有該類對象需要執行的代碼;而任何其它操作,都應該放在更適合這些工作的其它的類當中。但是!有時候會出現當前類當中需要的某個操作,應當放在另一個單獨的特殊類中更為合適,因為要保持類足夠的專用性;但不巧的是,這些操作又與當前的類有著密切聯系(例如會使用到當前類當中的成員(包括私有成員)等等)。正是這一類的情況,促使了內部類的誕生。 而更具體的來說,之所以使用內部類的原因,通常主要在于: - 在內部類當中可以訪問該類定義所在的作用域當中的任何數據,包括私有數據。(這是因為內部類會隱式的持有所在外部類的對象引用:“外部類名.this”) ~~~ package com.tsr.j2seoverstudy.base; public class Outer { private int num = 5; private class Inner { void printOuterNum() { /* * 1.驗證了內部類可以訪問其定義所在的作用域當中的任何屬性,包括被聲明為私有的屬性。 * 2.之所以內部類能訪問外部類的實例屬性,是因為其隱式的持有了外部類的對象:外部類類名.this */ System.out.println(num); System.out.println(Outer.this.num); } } } ~~~ 可以看到上面例子中雖然外部類“Outer”中的變量“num”被聲明為私有的,但定義在“Outer”當中的內部類仍然可以訪問到該成員變量。 - 內部類能夠針對于存在同一個包下的其他類,將自身隱藏起來。簡單的來說,該好處就是帶來更完善的類的封裝性。 ~~~ package com.tsr.j2seoverstudy.base; class Outer { private int num = 5; // 暴露給別人的方法接口 public void exposeMethod() { Inner in = new Inner(); System.out.println(in.doSomeThingSecret()); } private class Inner { int doSomeThingSecret() { // 封裝一些你不想暴露給其它人任何細節的方法 System.out.println("隱蔽的方法,叼!"); return num; } } } /* * 程序輸出結果為: * 隱蔽的方法,叼! * 5 */ public class Test{ public static void main(String[] args) { Outer out = new Outer(); out.exposeMethod(); } } ~~~ 通過該例子我們可以看到通過內部類實現帶來的嚴謹的封裝性。我們通過內部類“Inner”的方法“doSomeThingSecret”完成了一系列“秘密的操作”。 但我們提供給它人使用時,暴露給使用者的細節只有外部類當中的一個方法“exposeMethod”。這就很好的達到了我們的目的,隱藏不想讓別人知道的操作。 我們知道通常來講,類的訪問權限只能被修飾為public 或 默認的。這就意味著即使我們選擇相對較小的訪問權限:默認的包訪問權限。 那么我們定義的該類當中的實現細節,也會暴露給位于同一個包中的其它類。 而內部類允許被聲明為pirvate。這意味著:其它類甚至連我們定義了這樣的一個類都不知道,就更不用提該類當中的實現細節了。 - 通過匿名內部類能夠更為便捷的定義回調函數。以Java中的多線程機制為例: 如果不使用內部類,那么我們的實現方式就應該如同: ~~~ package com.tsr.j2seoverstudy.base; public class InnerDemo { public static void main(String[] args) { Assignment assignment = new Assignment(); Thread t = new Thread(assignment); t.start(); } } class Assignment implements Runnable{ @Override public void run() { System.out.println("線程任務"); } } ~~~ 而通過匿名內部類,我們可以將實現簡化為: ~~~ package com.tsr.j2seoverstudy.base; public class InnerDemo { public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { System.out.println("線程任務"); } }); t.start(); } } ~~~ 與我在之前的回顧中說到的一樣,“匿名”其實很好理解,直接的理解就是沒有名字。Java中的標示符就是名字。 所以,在第一種實現方式里,定義線程任務類的類名標示符“Assignment ”就是該線程任務類的類名。 而當我們將線程的任務通過第二種方式實現時,我們發現該其直接被作為參數傳遞給Thread類的構造函數當中。 沒有相關的類名標示符,那么這個線程任務類就是沒有名字的,所以被稱為“匿名”。 注:第三種使用方式應該是實際開發中最常用的。前兩種情況我個人在工作里很少用到,但很多知名的書中都介紹了,所以不妨也作為一種了解,總會有用得上的時候。 **創建內部類對象的方式** 在上面我們說過了,內部類當中是隱式的持有一個其所屬外部類的對象引用的。 由此就不能想象,一個內部類的對象創建肯定是依賴于其所屬的外部類的。 換句話說,要像創建使用一個內部類的對象,前提是必須先獲取到其所屬外部類的對象。 內部類的創建方式大概也就是兩種情況: - 在其所屬外部類當中,創建該內部類對象:這種情況與平常創建對象的方式沒有任何不同,也就是ClassName clazz = new ClassName();這樣的方式。 - 在其所屬外部類之外的類中創建內部類對象:因為我們說過了內部類對象的創建依賴于其所屬外部類,所以這是的創建方式為:Outer.Inner in = new Outer().new Inner()。 我們還是通過一道以前看見過的面試題,來更直觀的了解內部類的對象創建: ~~~ /* * 題目: * 1. public class Outer{ * 2. public void someOuterMethod() { * 3. // Line 3 * 4. } * 5. public class Inner{} * 6. public static void main( String[] args ) { * 7. Outer o = new Outer(); * 8. // Line 8 * 9. } * 10. } * * Which instantiates an instance of Inner? * A. new Inner(); // At line 3 * B. new Inner(); // At line 8 * C. new o.Inner(); // At line 8 * D. new Outer.Inner(); // At line 8 */ ~~~ 其實很簡單,只要牢記我們上面說的兩種創建情況就OK了。歸納來講:在創建內部類對象之前,必須先構造其外部類的對象。 所以當在外部類中創建內部類對象,因為外部類自身持有對象引用:this。所以可以直接創建內部類。 而在外部類之外創建內部類對象,則就需要先new Outer()創建得到外部類對象,再創建內部類對象。 由此我們來分別看該題目當中的4個答案: - A答案放在程序的第三行。是在其所屬外部類當中的實例方法中創建內部類對象,因為實例方法持有外部類對象引用this,所以可以直接創建。則A答案合法。 - B答案放在程序的第八行。雖然是在內部類本身創建內部類對象,但因為代碼是位于靜態方法當中,所以并不持有其外部類對象。所以B是非法的。 - C答案放在程序的第八行。代碼雖然位于靜態方法中,但因為之前已經創建了外部類對象“o”,所以再通過“o”創建內部類對象的方式是行得通的的。但要注意的是這種方式的正確使用形式應當是“o.Inner()”而非“new o.Inner()”。所以C也是非法的。 - D答案放在程序的第八行。乍看之下,十分完美。但要注意的是其使用的是“new Outer.”,而非通過new關鍵字調用類構造器創建對象的正確方式“new Outer().”。所以D自然也是非法的。 由此可以得出結論,合法的內部類實例聲明方式只有:A。 **局部內部類** 局部內部類是內部類之中一種稍顯特殊的使用方式。顧名思義,與“局部變量”相同,也就是被定義在方法或代碼塊當中的內部類。 關于局部內部類的使用,我覺得需要掌握的主要只有三點: 第一、與其它的局部成員一樣,局部類的有效范圍被限定在包含的代碼塊中,一旦超出該范圍,該局部內部類就不能被訪問了。 第二、局部內部類不能被訪問修飾符修飾,也就是說不能使用private、protected、public任一修飾符。因為作用域已經被限定在了當前所屬的局部塊中。 第三、這通常也是使用局部內部類的最常見原因。你可能也注意到了,普通的內部類雖然能訪問任何其所屬外部類的成員;但其所屬外部類定義的方法當中的局部變量是訪問不到的,使用局部內部類就可以解決這一問題。但必須謹記的是:被局部內部類訪問的變量必須被修飾為final。 ~~~ public class PartInnerDemo { int num_1 = 10; public void method(){ final int num_2 = 5; class PartInner{ private void InnerMethod(){ System.out.println(num_1+num_2); } } } } ~~~ ** ** **靜態內部類(嵌套類)** 靜態內部類可以說是內部類當中的一朵奇葩。開個玩笑,之所以這樣說是因為靜態內部類是比較特殊的一種內部類。 它的特性更像是一種嵌套類,而非內部類。因為我們前面說過了一般內部類當中,都會隱式的持有一個其所屬外部類的對象引用。而靜態內部類則不會。 除此之外,在任何非靜態內部類當中,都不能存在靜態數據。所以,如果想在內部類中聲明靜態數據,那么這個內部類也必須被聲明為靜態的。 當然,靜態類中除了靜態數據,也可以聲明實例數據。不同之處在于: 如果要在之外使用靜態內部類當中的靜態數據,那么可以直接通過該內部類的:類名.靜態成員名的方式。 而如果要只用該靜態內部類當中的實例成員,那么就必須如同其他非靜態內部類一樣,先創建該內部類的對象。 但同時需要注意,靜態內部類的對象創建與一般的內部類又有所不同,因為我們知道靜態內部類自身是不持有外部類的對象引用的,所以它不依賴于外部類的對象。簡單的說,我們可以認為靜態內部類自身也就是所屬外部類的一個靜態成員,所以其對象創建的方式為:Outer.Inner in = new Outer.Inner(); ~~~ public class StaticInner { void test() { int num_1 = Inner.num_1; // Inner in = new Inner(); int num = in.num; } private static class Inner { int num = 5; static int num_1 = 10; } ?? public static void main(String[] args) { ??? ?StaticInner.Inner in = new StaticInner.Inner(); ?} } ~~~ 說到這里,想起另外一個問題。這個問題在初學Java時一直沒能想清楚原因: ~~~ public class Test { public static void main(String[] args) { class Inner{ String name; Inner(String s){ name = s; } } Inner o = new Inner("test"); } } ~~~ 我們在前面說過,所有非靜態的內部類的實例化工作,都依賴于其外部類的對象實例化。 但在這段代碼中,我們對于定義的局部內部類“Inner”的對象創建卻沒有依賴于其所在外部類。 這應當是因為:因為該局部內部類被定義在一個靜態方法中,靜態方法中不會持有其所屬的類的對象引用this。 也就是說,定義在靜態方法當中的局部內部類遭受與靜態方法同樣的限制:不能訪問任何其所屬外部類的非靜態成員。 而內部類之所以持有其外部類對象引用的目的在于:可以訪問其所屬外部類的所有實例成員。 那么既然現在我已經被限制成不能訪問實例成員了,自然也就不必依賴于外部類的對象了。 **匿名內部類** 關于匿名內部類,其實在上面說為什么使用內部類的三種原因時,已經說過了。 匿名內部類的定義格式通常為: ~~~ new SuperType(constuction parameters){ //inner class method and data } ~~~ 對于匿名內部類,簡單來說就是一種內部類的簡寫形式。 而必須注意的是,對于匿名內部類的使用,其前提是:該內部類必須是繼承于一個外部類或者實現一個外部接口。 正如我們在上面說到的關于Java多線程。之所以能使用匿名內部類,是因為我們定義的匿名內部類實現了Runnable接口。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看