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類型的局部變量)

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

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, 由於構造器的名字必須和類名相同,而匿名類沒有類       名,所以匿名類不能有構造器

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

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

    在使用匿名內部類時,要記住以下幾個原則:
     ·匿名內部類不能有構造方法。  
     ·匿名內部類不能定義任何靜態成員、方法和類。  
     ·匿名內部類不能是public,protected,private,static。  
     ·只能創建匿名內部類的一個實例。
      ·一個匿名內部類一定是在new的後面,用其隱含實現一個接口或實現一個類。  
     ·因匿名內部類爲局部內部類,所以局部內部類的所有限制都對其生效。

      ·靜態內部類只能訪問外部類的靜態變量或靜態方法。


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文件,數字根據是第幾個匿名類而類推。

  Swing中使用內部類的例子如下:

package com.learnjava.innerclass;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;

public class SwingTest
{
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("JFrame");
        JButton button = new JButton("JButton");

        button.addActionListener(new ActionListener()
        {
            // new出來一個實現了ActionListener接口的類的實例

            @Override
            public void actionPerformed(ActionEvent arg0)
            {
                System.out.println("Hello World");

            }
        });

        //加入按鈕
        frame.getContentPane().add(button);

        //設置關閉行爲
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setSize(200, 200);
        
        frame.addWindowListener(new WindowAdapter()
        {
            //也可以使用繼承了適配器類的匿名內部類
            @Override
            public void windowClosing(WindowEvent e)
            {
            
                System.out.println("Closing");
                System.exit(0);
            }
        });
        frame.setVisible(true);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章