第十章:內部類:可以將一個類的定義放在另一個類的定義內部
- 內部類作用:
- 內部類可以起到隱藏和組織代碼的模式
- 內部類可以無條件的訪問外部類的任何成員(c++的嵌套類只是丹村的名字隱藏機制)
interface Selector{ boolean end(); Object current(); void next(); } 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; @Override public boolean end() { return i == items.length; } @Override public Object current() { return items[i]; } @Override public void next() { if(i < items.length){ i++; } } } public Selector selector(){ return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) { sequence.add(i); } Selector selector = sequence.selector(); while(!selector.end()){ System.out.println(selector.current()+" "); selector.next(); } } }
- 如果想從外部類的非靜態方法之外的任意位置創建某個內部類的對象,那麼必須使用OuterClassName.InterClassName
- .this/.new
- 如果你需要生成對外部類對象的引用,可以使用OuterClassName.this
- 用外部類創建某個內部類對象使用OuterClassObj.new
- 可以在一個方法裏面或者在任意的作用域內定義內部類,但是都是和其他類一起編譯
- 匿名內部類:
- 如果定義一個匿名內部類,並且希望它使用一個在其外部定義的對象,,那麼編譯器會要求其參數引用爲final
- 對於匿名類而言,實例初始化的實際效果就是構造器
- 匿名內部類與正規的繼承相比有些受限,因爲匿名內部類既可以擴展類,也可以實現接口,但是兩者不能兼具,而且如果實現接口,也只能實現一個接口
- 匿名工廠實現:
interface Service{ void method1(); void method2(); } interface ServiceFactory{ Service getService(); } class Implementation1 implements Service{ private Implementation1() { } @Override public void method1() { System.out.println("Implementation1 method1"); } @Override public void method2() { System.out.println("Implementation1 method2"); } public static ServiceFactory factory = new ServiceFactory() { @Override public Service getService() { return new Implementation1(); } }; } class Implementation2 implements Service{ private Implementation2() { // TODO Auto-generated constructor stub } @Override public void method1() { // TODO Auto-generated method stub System.out.println("Implementation2 method1"); } @Override public void method2() { // TODO Auto-generated method stub System.out.println("Implementation2 method2"); } public static ServiceFactory factory = new ServiceFactory() { @Override public Service getService() { // TODO Auto-generated method stub return new Implementation2(); } }; } public class Factories { public static void consumer(ServiceFactory sf){ Service s = sf.getService(); s.method1(); s.method2(); } @Test public void test(){ consumer(Implementation1.factory); consumer(Implementation2.factory); } }
- 如果不需要內部類對象與外圍類對象之間有聯繫,可以將內部類聲明爲static,通常稱爲嵌套類(與C++嵌套類的區別是,Java中可以訪問私有成員)
- 要創建嵌套類的對象,並不需要其外圍類的對象
- 不能從嵌套類的對象中訪問非靜態的外圍類對象
- 普通的內部類不能有static數據和static字段,也不能包含嵌套類
- 嵌套類可以作爲接口的一部分,接口的任何類都會被自動加上public static
- 爲什麼需要內部類
- 每個內部類都能獨立的繼承自一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響
- 內部類允許繼承多個非接口類型
- 當繼承了某個外部類的時候,內部類並沒有發生什麼特別神起的變化,這兩個內部類是完全獨立的兩個實體,各自在自己的命名空間內