程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 淺析Java中的嵌套類和內部類

淺析Java中的嵌套類和內部類

編輯:關於JAVA

以前看<Java編程思想>的時候,看到過嵌套類跟內部類的區別,不過後來就把它們的概念給忘了吧。昨天在看<數據結構與算法分析(Java語言版)>的時候,又遇到了這個概念,當時就很大的疑惑:嵌套類跟內部類有什麼區別?只有是否有關鍵字static的區別嗎?

所以今天找了個時間查了一下兩者的詳細區別,總結在這篇博客中,既方便自己的復習和學習,也啟示他人吧。

1,概念:

定義在一個類內部的類,叫作“嵌套類”。嵌套類分為兩種:static的和非static的。後者又有一個專門的名字,叫作“內部類”。所以從概念可以看出,嵌套類跟內部類是所屬關系,後者包含於前者。示例代碼如下:

class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}

同時,嵌套類是其所在類的成員。內部類可以訪問所在類的所有成員,即使該成員是private的。而static嵌套類則不得訪問所在類的成員。同時,嵌套類,static和非static的,都可以被聲明為private、public、protected和default的。

2,為什麼要使用嵌套類?

好處應該都比較文本化吧,以後在使用的過程中去理解和體會吧:對只在一個地方使用的類進行邏輯上的分組;增加了封裝性;易於閱讀和維護。

3,static嵌套類:

因為static嵌套類不能直接訪問所在類的非static成員變量和方法,所以static嵌套類必須通過綁定所在類的實例來進行訪問。而對於所在類的靜態成員和方法包括private、protected和public的,可以訪問。因為它也有static修飾。

static嵌套類通過寫出封裝的類名來進行實例化和訪問其內部成員:

OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();

4,內部類:

因為內部類是所在類的成員,所以它可以訪問所在類的任意變量和方法,但是它本身卻不能定義任何static的變量或方法。

同時,內部類的實例化方式也與static嵌套類有所不同:

OuterClass outerObject=new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

5,內部類的分類:

以前曾經接觸過內部類的分類,這裡一並總結一下:

以前的所謂的一些面試寶典裡面差不多都是將內部類分為四個種類:

靜態內部類(既static嵌套類)、成員內部類(既上述內部類)、局部內部類和匿名內部類。前兩者都已經介紹過了,下面專門看一下後面兩者。

5.1,局部內部類:

定義在方法內部的類叫作“局部內部類”。它的作用域僅限於方法作用域內,只能在方法的作用域內定義和實例化,是用處最小的類類型。和局部變量一樣,它不能被修飾為private, public, protected和static的,並且只能訪問方法內部定義的final變量。

class LocalInner
{
    int a = 1;
    
    public void doSomething()
    {
        int b = 2;
        final int c = 3;
        // 定義一個局部內部類
        class Inner3
        {
            public void test()
            {
                System.out.println("Hello World");
                System.out.println(a);
    
                // 不可以訪問非final的局部變量
                // error: Cannot refer to a non-final variable b inside an inner
                // class defined in a different method
                // System.out.println(b);
    
                // 可以訪問final變量
                System.out.println(c);
            }
        }
    
        // 創建局部內部類的實例並調用方法
        new Inner3().test();
    }
}
    
public class LocalInnerClassTest
{
    public static void main(String[] args)
    {
        // 創建外部類對象
        LocalInner inner = new LocalInner();
        // 調用外部類的方法
        inner.doSomething();
    }
    
}

5.2,匿名內部類:

顧名思義,匿名內部類就是沒有名字的局部類。它不使用關鍵字class, extends, implements以及構造函數。

它通常作為方法的一個參數傳入,比如在android開發中對一個Button添加一個OnClickListener監聽器。

匿名內部類隱匿的繼承了一個父類或者實現了一個接口。比如:

mUiHandler.post(new Runnable{
    @override
    public void run(){
    //
    }
    
});
    
AsyncClient.get(url, new JsonHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers,
                    JSONObject response) {
                // TODO Auto-generated method stub
                super.onSuccess(statusCode, headers, response);}} );

內部類通過將相關的類組織在一直,從而降低了命名空間的復雜性。

6,內部類的序列化問題。

對任何種類內部類(包括局部內部類和匿名內部類)的序列化都是不被鼓勵的。因為java編譯器在對內部類進行編譯的時候,將進行“合成構造”。合成構造使得java編譯器實現了java的新特性,但是卻沒有對JVM做出相應的改變。然而,不同的java編譯器對合成構造是有差別的,因而,如果對內部類進行了序列化,將使得不同的JRE實現中存在兼容性問題。

查看本欄目

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved