4.3 Java進階(三)內部類

一、內部類的概述

1、內部類,就是在一個類的內部在定義一個類。

2、分類:靜態內部類、成員內部類、局部內部類、匿名內部類

3、內部類的簡單應用:

(1)新建一個外部類Outer,在Outer裏寫一個內部類Inter

public class Outer {
	private int id=1001;
	private String name="admin";
	public void py()
	{
		System.out.println(id+"\t"+name);
	}
	public class Inter
	{
		public void play()
		{
			py();  //調用方法不可與本方法同名
		}
	}
}

(2)聲明內部類Inter方法一

public void test01()
	{	
		Outer.Inter oi=new Outer().new Inter();
		oi.play();
	}
	//輸出結果【1001	admin】

(3)聲明內部類Inter方法二

public void test02()
	{
		Outer o=new Outer();
		Outer.Inter oi=o.new Inter();
		oi.play();
	}
	//輸出結果【1001	admin】


二、內部類的實際應用

1、在User類中定義兩個內部類,分別是Teacher、Student,並添加帶參構造方法

public class User {
	private int id;
	private String name;
	private String sex;
	private String address;
	private String birth;
	private String phone;
	
	public User(int id, String name, String sex, String address, String birth, String phone) {
		this.id = id;
		this.name = name;
		this.sex = sex;
		this.address = address;
		this.birth = birth;
		this.phone = phone;
	}

	public void play(){
		System.out.println(id+"\t"+name+"\t"+sex+"\t"+address+"\t"+birth+"\t"+phone);
	}
	
	//內部類Teacher
	public class Teacher
	{
		int teaAge;
		public Teacher(int teaAge)
		{
			this.teaAge = teaAge;
		}
		
		public void show()
		{
			play(); //調用方法不可與本方法同名
			System.out.println(teaAge);
		}
	}
	
	//內部類Teacher
	public class Student
	{
		int pop;
		public Student(int pop) {
			this.pop = pop;
		}

		public void show()
		{
			play();
			System.out.println(pop);
		}
	}

}

2、調用內部類

public void test03()
	{
		User u=new User(1001,"張三","男","廣東廣州","1990-02-14","15018743146");
		User.Teacher teacher=u.new Teacher(7);
		teacher.show();
	}
	//輸出結果【1001	張三	男	廣東廣州	1990-02-14	15018743146  7】

三、靜態內部類

1、靜態內部類可以用public,protected,private,默認訪問權限修飾。

2、在靜態內部類中可以存在靜態成員和非靜態的成員,靜態內部類只能訪問外部類的靜態成員變量和方法,不能訪問外部類的非靜態成員變量和方法。

3、非靜態內部類中不能存在靜態成員,非靜態內部類中可以調用外部類的任何成員,不管是靜態的還是非靜態的。

4、代碼示例:

public class StaticOuter
{
	@SuppressWarnings("unused")
	private String sex;
    public static String name = "chenssy";

    /**
     *靜態內部類可以用public,protected,private,默認訪問權限修飾
     */
    static class InnerClass1
    {
        int inner_i = 100;
        public static String name1 = "chenssy_static";  //在靜態內部類中可以存在靜態成員和非靜態的成員

        public void display()
        {
            System.out.println("OutClass name :" + name);    //靜態內部類只能訪問外部類的靜態成員變量和方法, 不能訪問外部類的非靜態成員變量和方法
        }
    }

    /**
     * 非靜態內部類
     */
    class InnerClass2
    {
        public String name2 = "chenssy_inner";  //非靜態內部類中不能存在靜態成員
        public void display(){
            System.out.println("OuterClass name:" + name);    //非靜態內部類中可以調用外部類的任何成員,不管是靜態的還是非靜態的
        }
    }

    /**
     * 外部類方法
     */
    public void display()
    {
        System.out.println(InnerClass1.name1);  //外部類可以直接訪問靜態內部類的靜態成員:[內部類.靜態成員]
        new InnerClass1().display();    //靜態內部類可以直接創建實例不需要依賴於外部類, 外部類訪問內部類的非靜態成員,實例化內部類即可
        StaticOuter.InnerClass2 inner2 = new StaticOuter().new InnerClass2(); //非靜態內部的創建需要依賴於外部類
        System.out.println(inner2.name2);   //訪問非靜態內部類的成員需要使用非靜態內部類的實例
        inner2.display();
    }

    public static void main(String[] args) 
    {
    	StaticOuter outer = new StaticOuter();
        outer.display();
    } 
    /*
     * 輸出結果:
     * chenssy_static
       OutClass name :chenssy
       chenssy_inner
       OuterClass name:chenssy
     */
}


四、成員內部類

1、成員內部類中不能存在任何static的變量,static方法和static代碼塊

2、成員內部類是依附於外部類的,所以只有先創建了外部類才能夠創建內部類。

3、代碼示例:

public class MemberOuter
{
	private static int i = 1;
    private int j = 10;
    private int k = 20;

    public static void outer_f1()
    {
    	
    }

    public void outer_f2()
    {
    	
    }
    class Inner 
    {
        // static int inner_i = 100;     
    	//成員內部類中不允許定義靜態成員
        int j = 100;     //內部類和外部類的變量可以同名
        int inner_i = 1;

        void inner_f1() 
        {
            System.out.println(i);  // 成員內部類中,可以訪問外部類的所有成員
            System.out.println(j);  //在內部類中訪問內部類自己的變量直接用變量名
            System.out.println(this.j); //在內部類中訪問內部類自己的變量也可以用this.變量名
            System.out.println(MemberOuter.this.j);   //在內部類中訪問外部類中與內部類同名的實例變量用外部類名.this.變量名
            System.out.println(k);  //如果內部類中沒有與外部類同名的變量,則可以直接用變量名訪問外部類變量
            outer_f1(); //成員內部類中,可以訪問外部類的所有成員
            outer_f2(); //成員內部類中,可以訪問外部類的所有成員
        }
    }
    //外部類的非靜態方法訪問成員內部類(和使用普通類沒什麼區別)
    public void outer_f3() 
    {
        Inner inner = new Inner();
        inner.inner_f1();
    }
    // 外部類的靜態方法訪問成員內部類,與在外部類的外部訪問成員內部類一樣,應該具體的指出這個對象的類型:OuterClassName.InnerClassName
    public static void outer_f4() 
    {
        //step1 建立外部類對象
        MemberOuter out = new MemberOuter();
        //step2 根據外部類對象建立內部類對象
        Inner inner = out.new Inner();
        //step3 訪問內部類的方法
        inner.inner_f1();
    }

    public static void main(String[] args) {
        //outer_f4();   //該語句的輸出結果和下面三條語句的輸出結果一樣
        //如果要直接創建內部類的對象,不能想當然地認爲只需加上外部類Outer的名字就可以按照通常的樣子生成內部類的對象,而是必須使用此外部類的一個對象來創建其內部類的一個對象
        //Outer.Inner outin = out.new Inner();      //這是錯的
        //因此,除非你已經有了外部類的一個對象,否則不可能生成內部類的對象。因爲此內部類的對象會悄悄地鏈接到創建它的外部類的對象。如果你用的是靜態的內部類,那就不需要對其外部類對象的引用。
    	MemberOuter out = new MemberOuter();
    	MemberOuter.Inner outin = out.new Inner();
        outin.inner_f1();
    }
    /*
     * 輸出結果:
     * 1
       100
       100
       10
       20
     */
}


五、局部內部類

public class PartOuter
{
	@SuppressWarnings("unused")
	private void internalTracking(boolean b)
	{
        if(b)
        {
            class TrackingSlip
            {
                private String id;
                TrackingSlip(String s) 
                {
                    id = s;
                }
                String getSlip()
                {
                    return id;
                }
            }
            TrackingSlip ts = new TrackingSlip("chenssy");
            String string = ts.getSlip();

        }
    }

    public void track(){
        internalTracking(true);
    }

    public static void main(String[] args) 
    {
    	PartOuter parcel = new PartOuter();
        parcel.track();
    }
}


六、匿名內部類

1、匿名內部類就是沒有名字的內部類。

2、使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口, 當然也僅能只繼承一個父類或者實現一個接口。

3、如果滿足下面的一些條件,使用匿名內部類是比較合適的: 

(1)只用到類的一個實例。

(2)類在定義後馬上用到。 

(3)類非常小(推薦是在4行代碼以下)

(4)給類命名並不會導致你的代碼更容易被理解。

4、代碼示例:

public class AnOuter
{
	public InnerClass getInnerClass(final int num,String str2)
	{
        return new InnerClass()
        {
            int number = num + 3;
            public int getNumber(){
            	
                return number;
            }
        };        /* 注意:分號不能省 */
    }
    
    public static void main(String[] args) 
    {
    	AnOuter out = new AnOuter();
        InnerClass inner = out.getInnerClass(2, "chenssy");
        System.out.println(inner.getNumber());
    }   //輸出結果【5】
}

interface InnerClass 
{
    int getNumber();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章