Java 內部類種類及使用解析【轉】


內部類Inner Class

  將相關的類組織在一起,從而降低了命名空間的混亂。

  一個內部類可以定義在另一個類里,可以定義在函數里,甚至可以作為一個表達式的一部分。

  Java中的內部類共分為四種

  靜態內部類static inner class (also called nested class)

  成員內部類member inner class

  局部內部類local inner class

  匿名內部類anonymous inner class

 

靜態內部類Static Inner Class

  最簡單的內部類形式。

  類定義時加上static關鍵字。

  不能和外部類有相同的名字。

  被編譯成一個完全獨立的.class文件,名稱為OuterClass$InnerClass.class的形式。

  只可以訪問外部類的靜態成員和靜態方法,包括了私有的靜態成員和方法。

  生成靜態內部類對象的方式為:

  OuterClass.InnerClass inner = new OuterClass.InnerClass();

  靜態內部類使用代碼:

靜態內部類使用測試

package com.learnjava.innerclass;

class StaticInner
{
    private static int a = 4;

    // 靜態內部類
    public static class Inner
    {
        public void test()
        {
            // 靜態內部類可以訪問外部類的靜態成員
            // 並且它只能訪問靜態的
            System.out.println(a);
        }

    }
}

public class StaticInnerClassTest
{

    public static void main(String[] args)
    {
        StaticInner.Inner inner = new StaticInner.Inner();
        inner.test();
    }
}

  

成員內部類Member Inner Class

  成員內部類也是定義在另一個類中,但是定義時不用static修飾。

  成員內部類和靜態內部類可以類比為非靜態的成員變量和靜態的成員變量。

  成員內部類就像一個實例變量。

  它可以訪問它的外部類的所有成員變量和方法,不管是靜態的還是非靜態的都可以

  在外部類里面創建成員內部類的實例:

  this.new Innerclass();

  在外部類之外創建內部類的實例:

  (new Outerclass()).new Innerclass();

  在內部類里訪問外部類的成員:

  Outerclass.this.member

  詳情見代碼例子:

成員內部類使用測試

package com.learnjava.innerclass;

class MemberInner
{
    private int d = 1;
    private int a = 2;

    // 定義一個成員內部類
    public class Inner2
    {
        private int a = 8;

        public void doSomething()
        {
            // 直接訪問外部類對象
            System.out.println(d);
            System.out.println(a);// 直接訪問a,則訪問的是內部類里的a

            // 如何訪問到外部類里的a呢?
            System.out.println(MemberInner.this.a);
        }

    }

}

public class MemberInnerClassTest
{

    public static void main(String[] args)
    {

        // 創建成員內部類的對象
        // 需要先創建外部類的實例
        MemberInner.Inner2 inner = new MemberInner().new Inner2();

        inner.doSomething();
    }
}

局部內部類Local Inner Class

  局部內部類定義在方法中,比方法的范圍還小。是內部類中最少用到的一種類型。

  像局部變量一樣,不能被public, protected, private和static修飾。

  只能訪問方法中定義的final類型的局部變量。

(內部類並不是直接調用方法傳進來的參數,而是內部類將傳進來的參數通過自己的構造器備份到了自己的內部,自己內部的方法調用的實際是自己的屬性而不是外部類方法的參數。  
這樣理解就很容易得出為什么要用final了,因為兩者從外表看起來是同一個東西,實際上卻不是這樣,如果內部類改掉了這些參數的值也不可能影響到原參數,然而這樣卻失去了參數的一致性,因為從編程人員的角度來看他們是同一個東西,如果編程人員在程序設計的時候在內部類中改掉參數的值,但是外部調用的時候又發現值其實沒有被改掉,這就讓人非常的難以理解和接受,為了避免這種尷尬的問題存在,所以編譯器設計人員把內部類能夠使用的參數設定為必須是final來規避這種莫名其妙錯誤的存在。簡單理解就是,拷貝引用,為了避免引用值發生改變,例如被外部類的方法修改等,而導致內部類得到的值不一致,於是用final來讓該引用不可改變)

  局部內部類在方法中定義,所以只能在方法中使用,即只能在方法當中生成局部內部類的實例並且調用其方法。

局部內部類使用測試

package com.learnjava.innerclass;

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();
    }

}

匿名內部類Anonymous Inner Class

  匿名內部類就是沒有名字的局部內部類,不使用關鍵字class, extends, implements, 沒有構造方法。

  匿名內部類隱式地繼承了一個父類或者實現了一個接口

  匿名內部類使用得比較多,通常是作為一個方法參數。

匿名內部類使用測試

package com.learnjava.innerclass;

import java.util.Date;

public class AnonymouseInnerClass
{

    @SuppressWarnings("deprecation")
    public String getDate(Date date)
    {
        return date.toLocaleString();

    }

    public static void main(String[] args)
    {
        AnonymouseInnerClass test = new AnonymouseInnerClass();

        // 打印日期:
        String str = test.getDate(new Date());
        System.out.println(str);
        System.out.println("----------------");

        // 使用匿名內部類
        String str2 = test.getDate(new Date()
        {
        });// 使用了花括號,但是不填入內容,執行結果和上面的完全一致
            // 生成了一個繼承了Date類的子類的對象
        System.out.println(str2);
        System.out.println("----------------");

        // 使用匿名內部類,並且重寫父類中的方法
        String str3 = test.getDate(new Date()
        {

            // 重寫父類中的方法
            @Override
            @Deprecated
            public String toLocaleString()
            {
                return "Hello: " + super.toLocaleString();
            }

        });

        System.out.println(str3);
    }
}

 生成的.class文件中,匿名類會生成OuterClass$1.class文件,數字根據是第幾個匿名類而類推。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com