天天看點

《Thinking in java》——内部類小結

1、在一個類A中定義了一個内部類B之後,如果要在外部類中執行個體化這個内部類B的話,必須要有類A的引用才能夠使用new執行個體化一個内部類。例子如下所示:

public class DotNew {

	public class Inner{
		
	}
	
	public static void main(String[] args){
		
		DotNew dotNew = new DotNew();
		Inner inner = dotNew.new Inner();
	}
}
           

2、如果要在内部類B中獲得其外部類A的引用,可以使用外部類的類名+.this 關鍵字。例子如下所示:

public class DotThis {

	void f(){
		
		System.out.println("DotThis.f()");
	}
	
	public class Inner{
		
		public DotThis outer(){
			
			return DotThis.this;
		}
	}
	
	public Inner inner(){
		
		return new Inner();
	}
	
	public static void main(String[] args){
		
		DotThis dotThis = new DotThis();
		DotThis.Inner inner = dotThis.inner();
		inner.outer().f();
	}
}
           

3、如果一個外部類A中有内部類B,并且該内部類B是嵌套類(靜态内部類),則要執行個體化這個内部類時,不需要引用外部類的執行個體。例子代碼如下所示:

public class Parcel3 {

	static class StaticDestination{
		
		private String label;
		
		StaticDestination(String whereTo) {
			this.label = whereTo;
		}
		
		String readLabel(){
			
			return label;
		}
		
	}
	
	public static void main(String[] args){
		
		Parcel3.StaticDestination staticDestination = new Parcel3.StaticDestination("Tasmania");
	}
}
           

4、内部類可以定義在類中,也可以定義在方法中、方法的某個範圍中。例子代碼如下所示:

public class Parcel6 { 
  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("slip"); 
      String s = ts.getSlip(); 
    } 
    // 超出内部類的定義範圍,無法通路這個内部類
    //! TrackingSlip ts = new TrackingSlip("x"); 
  }  
  public void track() { internalTracking(true); } 
  public static void main(String[] args) { 
    Parcel6 p = new Parcel6(); 
    p.track(); 
  } 
} 
           

5、匿名内部類使用預設構造器,如果其基類的構造方法需要傳參數,那麼這個匿名内部類的構造方法也需要傳參數。不傳參數的話,編譯器會報錯。而且該匿名内部類看起來是繼承或者實作了基類。例子代碼如下所示:

public class Parcel8 {
	
	class Wrapping{
		
		private int x;
		
		public Wrapping(int x) {

			this.x = x;
		}
		
		int value(){
			return x;
		}
	}

	public Wrapping warrping(int x){
		return new Wrapping(x){

			@Override
			int value() {
				return super.value()*47;
			}
			
		};
	}
}
           

6、在匿名内部類中如果該匿名内部類中需要直接引用外部類的變量,則該變量必須是final 的。上例中因為沒有直接在匿名内部類中引用x,隻是構造方法傳參數進去,是以x不需要是final 的。代碼例子如下所示:

abstract class Destination{
	
	abstract String readLabel();
}

public class Parcel10 {

	public Destination destination(final String dest,final float price){
		
		return new Destination(){
			
			private int cost;
			
			{
				cost = Math.round(price);
				if(cost>100){
					System.out.println("Over budget!");
				}
			}
			
			private String label = dest;
			
			@Override
			String readLabel() {
				return label;
			}
			
		};
	}
	
	public static void main(String[] args){
		
		Parcel10 parcel10 = new Parcel10();
		parcel10.destination("Tasmania", 101.95F);
	}
}
           

7、匿名内部類有點類似于平常的繼承,因為它們可以繼承一個類或者實作一個接口,但是不能兩者都有。如果是實作一個接口的話,隻能實作一個接口。 

8、如果在内部類和外部類之間不需要連接配接的話,則可以使用嵌套類,即這個内部類是靜态的(static)的。使用嵌套類意味着:

a、不需要使用外部類來建立一個嵌套類對象。

b、不能從嵌套類通路非靜态的外部類的對象。

c、可以有靜态域、靜态資料。

d、嵌套類内部可以有嵌套類。

而普通的内部類與嵌套類相比較而言,有以下不同點:

a、必須通過外部類的引用來建立一個内部類的對象。

b、内部類可以通路外部類的的域、方法(靜态非靜态都可以)。

c、普通内部類不能定義靜态域、靜态方法,也不能定義嵌套類,不過可以定義常量(static final的常量)

9、嵌套類可以是接口的一部分。因為在接口中的所有類都預設是public和static的,是以在接口中定義嵌套類并不違反接口的規則。例子代碼如下所示:

public interface ClassInInterface {

	void howdy();
	
	class Test implements ClassInInterface{

		@Override
		public void howdy() {
			
			System.out.println("Test.howdy()");
		}
		
		public static void main(String[] args){
			
			new Test().howdy();
		}
		
	}

}
           

未完待續。