天天看點

黑馬程式員——java基礎----面向對象(三)内部類

------ Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練、期待與您交流! ------- 内部類 1,什麼叫内部類?

         顧名思義,内部類就是定義在一個類中的類。

2,為什麼會有内部類?怎麼來的?

         當我們進行java開發時,有時需要實作一個僅包含1-2個方法的接口。

例 : 在學習集合架構的時候,有一個疊代器(Iterator接口),它裡面就有一個方法iterator(),是專門用來給Colleaction集合進行疊代的,檢視其底層發現它是嵌入在集合接口内部的。

例 : 在我們學習GUI時,當一個display元件需要一個事件回調方法時,如:一個按鈕的ActionListener時,也是用到了内部類。 那麼,以上兩個例子要說明什麼呢?

        通過上面兩個例子,我們會發現,如果我們不用内部類的方式來完成,而是使用普通類來實作這些操作,最終會得到很多僅在單個位置上使用的小型類,僅僅是為類一個小小的功能,就要建立一個類,是不是有點浪費呢? 是以為了解決這個問題就出現了内部類這個看上去很難懂的類。

當然,内部類還有很多理由值得我們來用, 

  理由(1)内部類可以直接通路外部類中的成員,包括私有。

  理由(2)内部類可以對同一個包中的其它類隐藏起來。

  理由(3)當想要定義一個回調函數且不想編寫大量代碼時,使用匿名内部類比較友善。

3,内部類的通路規則

        (1)内部類可以直接通路外部類中的成員,包括私有。之是以可以直接通路外部類中的成員,是因為内部類中持有了一個外部類引用,格式:外部類名.this。

        (2)外部類要通路内部類,必須要建立内部類對象。

代碼:

//外部類
class Outer {
	//外部類私有成員變量
	private int x = 3;//Outer.this.x
     //内部類
	class Inner {
		//内部類成員
		int x = 4;//this.x
		//内部類成員方法
		void function() {
	                //内部類局部變量
			int x = 6;//x
			System.out.println("Inner :" + x);//6
			System.out.println("Inner :" + this.x);//4
			//内部類可以直接通路外部類成員,包括私有
			System.out.println("Inner :" +Outer.this. x);//3
		}
	}
    //外部類成員方法
	void method() {
       //建立内部類成員變量
       Inner in = new Inner();//外部類要通路内部類必須要建立内部類對象。
       //調用内部類成員方法
       in.function();
	}

}
//測試類
public class InnerDemo {
	public static void main(String[] args) {
		//建立外部類對象
		Outer out = new Outer();
		//調用外部類成員方法。
		out.method();
             //直接通路内部類中的成員方法
              Outer.Inner outin = new Outer().new Inner();
              outin.function(); 
	}
}
           

4,當内部類在成員位置上,并且被修飾符所修飾。

         比如:private:将内部類在外部類中進行封裝。

                      static:内部類具備靜态的特性。 當内部類被static修飾後,隻能直接通路外部類的static成員。出現了通路權限。 代碼:

//外部類
class Outer1
{  
   //私有靜态成員變量
   private static int x= 3;
   //靜态内部類1
    static class Inner1{
    	//靜态内部類中的靜态成員變量
	    static int x = 4;
	    //靜态内部類中的靜态成員方法
	     static void function(){
	    	 //非靜态通路了靜态
		     int x = 5;
		    //列印靜态成員方法中的非靜态變量 
		   System.out.println(x);
		   //列印靜态内部類中靜态成員變量
		   System.out.println(Inner1.x);
		   //列印外部類的靜态成員變量
	           System.out.println(Outer1.x);
		   
	   }
   } 
    //靜态内部類2
    static class Inner2{
    	//靜态内部類的非靜态成員方法
    	void function(){
                 //靜态内部類通路外部類的靜态成員變量
    		 System.out.println(Outer1.x);
    	}
    }
}
//測試類
public class InnerDemo2 {
	public static void main(String[] args) {
		//外部類通路靜态内部類的靜态方法
		Outer1.Inner1.function();
		//外部類通路靜态内部類的非靜态方法
                new Outer1.Inner2().function();
       
	}

}
           

注意:當内部類中定義了靜态成員,該内部類必須是靜态的。(因為靜态隻能通路靜态)

            當外部類的靜态方法通路内部類時,内部類必須是靜态的(同上)

5,什麼時候使用内部類?

            當描述事物時,事物的内部還有事物,該事物用内部類來描述。因為内部類事物在使用外部類事物的内容。

6,當内部類定義在局部時

         (1)不可以被成員修飾符修飾。

         (2)可以直接通路外部類中的成員,因為還持有外部類的引用。但是不可以通路它所在的局部中的變量,隻能通路被final修飾的局部變量。

代碼:

//外部類
class Outer2{
	int x = 3;//Outer2.this.x
	void method(final int a){
	      final int y = 4;
		//局部内部類
		class Inner{
		     void function(){
			//局部内部類通路局部變量時,該變量必須是final常量。
			System.out.println(y);
			System.out.println(a);
			System.out.println(x);//還持有外部類的引用
		     }
		}
		//外部類成員方法通路局部内部類的成員方法。
		new Inner().function();
	}
	
}
//測試類
public class InnerDemo3 {
	public static void main(String[] args) {
	   //調用方法	
	   new Outer2().method(7);
	}

}
           

7,匿名内部類

      (1)匿名内部類其實就是内部類的簡寫格式。

      (2)定義匿名内部類前提:内部類必須是繼承一個類或者實作接口。

      (3)匿名内部類的格式:new 父類或者接口(){定義子類的内容}

      (4)匿名内部類是一個匿名子類對象,可以了解為帶内容的對象。

      (5)匿名内部類中定義的方法最好不要超過三個。

代碼:

//抽象類
abstract class AbsDemo{
        //抽象方法
	abstract void show();
}
//外部類
class Outer3{
	int x = 3;
	public void function(){
		//建立匿名内部類的對象
		AbsDemo d= new AbsDemo(){//父類引用指向子類對象
			void show(){
				System.out.println(x);
			}
		};
		//實作接口的子類對象調用複寫父類的方法。
		d.show();
//-------------------------------------------------------------------		
		//通過匿名内部類的匿名子類對象來調用複寫父類的方法。
		new AbsDemo(){//父類引用指向子類對象
			void show(){
				System.out.println(x);
			}
		}.show();	
	}
}
//測試類
public class InnerDemo4 {
      public static void main(String[] args) {
       //通過外部類匿名對象調用方法
        new Outer3().function();
}