《編程思想》9.內部類

一.創建內部類
(1)內部類瞭解外圍類,並能與之通信
(2)創建內部類方式:把類的定義置於外圍類的裏面

public class Parcel1 {
	
	//內部類1
	class Contents{
		private int i = 11 ;
		public int value(){
			return i ;
		}
	}
	
	//內部類2
	class Destination{
		private String label ;
		Destination(String whereTo){
			label = whereTo;
		}
		String readLabel(){
			return label ;
		}
	}
	
	public void ship(String dest){
		//創建內部類
		Contents c = new Contents();
		Destination d = new Destination(dest);
		System.out.println(d.readLabel());
	}
	
	public static void main(String[] args) {
		 Parcel1 p = new Parcel1();
		 p.ship("Tasmaia");
	}

}

二.鏈接到外部類
1.當生成一個內部類的對象時,此對象與製造它的外圍對象之間就有了一種聯繫,所以能訪問其外圍對象的所有成員,而不需要任何條件。內部類還擁有其外圍類所有元素的訪問權。

2.內部類自動擁有對其外圍所有成員的訪問權。

public class Sequence {
	private Object[] items ;
	private int next = 0 ;
	public Sequence(int size){
		items = new Object[size];
	}
	public void add(Object x){
		if(next < items.length){
			items[next++] = x ;
		}
	}
	
	//內部類
	private class SequenceSelector implements Selector{
        private int i = 0 ; 
		public boolean end() { 
			//調用外部類的方法  items爲private
			return i == items.length;
		} 
		public Object current() { 
			return items[i];
		} 
		public void next() {  
			if(i < items.length)
				i ++ ;
		} 
	}
	
	public Selector selector(){
		//生成內部類對象
		return new SequenceSelector();
	}
	public static void main(String[] args) {
		 //...
	}

}

三.使用.this與.new

public class MainJava { 
	 void f(){
		 System.out.println("DotThis.f()");
	 }
	 public class Inner{
		 public MainJava outer(){
		    //內部類生成對外部類對象的引用
			 return MainJava.this; //MainJava 爲外部類
		 }
	 }
	 public Inner inner(){
		 return new Inner();
	 }
	 public static void main(String[] args) {  
		 MainJava dt = new MainJava();
		 MainJava.Inner dti = dt.inner();
		 dti.outer().f();
	 } 
}


//創建內部類對象
public class DotNew{
  public class Inner{};
  public static void main(String[] args){
    DotNew dn = new DotNew(); //生成外部類對象
    DotNew.Inner dni = dn.new Inner(); //生成內部類對象
   }
 }

要想直接創建內部類的對象,你不能按照你想象的方式,去引用外部類的名字DotNew,而是必須使用外部類的對象來創建改內部類對象。
擁有外部類對象之前是不可能創建內部類對象的。

4.內部類與向上轉型
(1)當將內部類向上轉型爲基類,尤其是轉型爲一個接口的時候,內部類就有了用武之地。

5.在方法和作用域內的內部類
可以在一個方法裏面或者在任意的作用域內定義內部類。

6.匿名內部類
(1)不使用匿名內部類

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

(2)使用匿名內部類

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

(3)在接口上使用匿名內部類


interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

只要一個類是抽象的或是一個接口,那麼其子類中的方法都可以使用匿名內部類來實現

最常用的情況就是在多線程的實現上,因爲要實現多線程必須繼承Thread類或是繼承Runnable接口

(4)Thread類的匿名內部類實現


public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

(5).匿名內部類只能使用一次,它通常用來簡化代碼編寫

(6).但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口

9.爲什麼需要內部類
(1)使用內部類最吸引人的原因是:
每個內部類都能獨立地繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。

(2)內部類使得多重繼承的解決方案變得完整

//即必須在一個類中以某種方式實現兩個接口。由於接口的靈活性,可以使用單一類或內部類
interface A{}

interface B{}

class X implements A,B{}

class Y implements A {
    B makeB(){
      return new B(){};
     }
  }

public class MultiInterfaces{
   static void takesA(A a){}
   static void takesB(B b){}
   public static void main(String[] args){
      X x = new X();
      Y y = new Y();
      takesA(x);
      takesA(y);
      takesB(x);
   }
 }
//如果擁有的是抽象的類或具體的類,而不是接口,那就只能使用內部類才能實現多重繼承
class D {}

abstract class E {
  abstract void A();
}

class Z extends D {
   E makeE(){
       //匿名內部類 
	   return new E() {
       void A() { 
				
			}};
   };
  }
  }

public class MultiImplementation{
    static void takesD(D d){}
    static void takesE(E e){}
    public static void main(String[] args){
        Z z = new Z();
        takesD(z);
        takesE(z.makeE());
      }
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章