Java內部類詳解(二)

三、種類

局部內部類、成員內部類、匿名內部類、靜態內部類。

1. 局部內部類

局部內部類:是指內部類定義在方法或代碼塊內的類。

1.1 與局部變量一樣,不能用public, protected, private和static修飾。

1.2 只能訪問外部類的方法或代碼塊中定義爲final類型的局部變量。

1.3 只能在方法或代碼塊中使用,即只能在方法或代碼塊當中生成局部內部類的實例並且調用其方法,並不對外界透明。

例子:

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

2. 成員內部類

成員內部類:定義在外部類方法之外的類,即外部類的成員。

2.1 可以直接使用外部類的所有成員和方法,不論是靜態的,還是非靜態的,即使是private的也可以訪問。

可直接使用Outer.this表示外部類對象。

2.2 外部類要訪問內部類的所有成員變量/方法,則需要通過內部類的對象來獲取,而不能通過inner.this。例如:

public class Outer {

//	private Inner inner = new Inner();
//	private String a = inner.b;
//	private String a = inner.getB();

	private String a = new Inner().b;
	
	private class Inner {
		
		private String b = "11";
		
		public String getB() {
			return b + "22";
		}
	}
	
	public String getA() {
		return a;
	}
	
	public static void main(String[] args) {
		Outer outer = new Outer();
		System.out.println(outer.getA());
	}
}

 2.3 其他類要直接創建內部類,必須首先創建外部類,且受訪問級別的限制。

Inner inner = (new Outer()).new Inner()

2.4 成員內部類不能含有static的變量和方法(除非定義爲static final)。因爲成員內部類需要先創建了外部類,才能創建它自己的,瞭解這一點,就可以明白更多事情,在此省略更多的細節了。

例子:

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

3. 匿名內部類

3.1 就是沒有名字的局部內部類。

3.2 與局部內部類不同的是,匿名內部類的類必須是預先定義好的已存在的類或接口。

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

3.4 因爲沒名字,因而默認只有無參數的構造函數,如果需要參數的,則需要該類有帶參數的構造函數。例如:

public class Outer {
	public static void main(String[] args) {
		Outer outer = new Outer();
		Inner inner = outer.getInner("Inner", "gz");
		System.out.println(inner.getName());
	}

	public Inner getInner(final String name, String city) {
		// 注意這裏的形參city,由於它沒有被匿名內部類直接使用,而是被抽象類Inner的構造函數所使用,所以不必定義爲final。
		return new Inner(name, city) {
			private String nameStr = name;

			public String getName() {
				return nameStr;
			}
		};
	}
}

abstract class Inner {
	Inner(String name, String city) {
		System.out.println(city);
	}

	abstract String getName();
}

 例子:

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

4. 靜態內部類

4.1 就是靜態的成員內部類。定義時加上static。

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

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

4.4 可以直接引用Outer.Inner,即不需要創建外部類。

Outer.Inner inner = new Outer.Inner();

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

 

發佈了110 篇原創文章 · 獲贊 197 · 訪問量 320萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章