1、 內部類特性html
2、 匿名內部類app
1. ide
1 public class Parcel7 2 { 3 public Contents contents() 4 { 5 return new Contents() 6 { 7 private int i = 11; 8 public int value() { return i; } 9 }; 10 } 11 public static void main(String[] args) 12 { 13 Parcel7 p = new Parcel7(); 14 Contents c = p.contents(); 15 } 16 }
在上述代碼中, contents() 方法將返回值的生成與表達這個返回值的類定義結合在一塊兒。另外,這個類是匿名的,它沒有名字。spa
語法:建立一個繼承自Contents的匿名類的對象。經過new表達式返回的引用被自動向上轉型爲對Contents的引用。(向上轉型內容參照:http://www.javashuo.com/article/p-wpymcfzm-nw.html)code
關於分號的說明:在匿名內部類末尾的分號,並非用來標記此內部類結束的。實際上,它標記的是表達式的結束,只不過這個表達式正巧包含了匿名內部類,所以,這與別的地方使用的分號是一致的。htm
上述匿名內部類的代碼,是下面代碼的簡化版本:對象
1 public class Parcel7 2 { 3 public MyContents implements contents 4 { 5 private int i = 11; 6 public int value() { return i; } 7 } 8 public Contents contents() { return new MyContents(); } 9 public static void main(String[] args) 10 { 11 Parcel7 p = new Parcel7(); 12 Contents c = p.contents(); 13 } 14 }
在這個匿名類中,使用了默認的構造器來生成Contents。blog
2. 下面代碼展現了基類須要一個有參數的構造器繼承
1 public class Wrapping 2 { 3 private int i; 4 public Wrapping(int x) { i = x; } 5 public int value() { return i; } 6 } 7 ////////////////////////////////////////// 8 public class Parcel8 9 { 10 public Wrapping wrapping(int x) 11 { 12 return new Wrapping(x) 13 { 14 public int value() 15 { 16 return super.value() * 47; 17 } 18 }; 19 } 20 public static void main(String[] args) 21 { 22 Parcel8 p = new Parcel8(); 23 Contents w = p.wrapping(); 24 } 25 }
在該例子中,能夠看到Wrapping擁有一個要求傳遞參數的構造器。接口
這裏是將x傳進new Warpping(x)。
在匿名內部類中,只須要簡單地傳遞合適的參數給基類的構造器便可。
3. 在匿名內部類定義中,對其進行初始化操做
1 public class Parcel9 2 { 3 public Destination destination(final String dest) 4 { 5 return new Destination() 6 { 7 private String lable = dest; 8 public String readLable() { return lable; } 9 }; 10 } 11 public static void main(String[] args) 12 { 13 Parcel9 p = new Parcel9(); 14 Destination d = p.destination("Tasmaina"); 15 } 16 }
在new Destination()中,使用到了在其外部定義的變量dest,編譯器要求咱們引用的參數是final的
即: 若是定義一個匿名內部類,而且但願他使用一個在其外部定義的對象,那麼編譯器會要求其參數引用final的。
4.
若是隻是簡單的給一個字段賦值,那麼3例中的方法是很好的。可是,若是想作一個相似構造器的行爲,可是匿名類中不可能有命名構造器(其緣由是由於它根本就沒有名字)。經過實例初始化,就可以達到爲匿名內部類建立一個構造器的效果。具體實例以下:
1 abstract class Base 2 { 3 public Base(int i) 4 { 5 System.out.println("Base coustructor. i = " + i); 6 } 7 public abstract void f(); 8 } 9 public class AnonymousConstructor 10 { 11 public static Base getBase(int i) 12 { 13 return new Base(i) 14 { 15 { System.out.println("Inside instance initializer "); } 16 public void f() 17 { 18 System.out.println("In anonymous f()"); 19 } 20 }; 21 } 22 public static void main(String[] args) 23 { 24 Base base = getBase(47); 25 base.f(); 26 } 27 }
注意: 在此例中,並無要求變量 i 必定是final的,由於 i 被傳遞給匿名類的基類的構造器,並無在匿名類內部被直接使用。
5. 下面代碼爲帶實例初始化的形式
1 public class Parcel10 2 { 3 public Destination destination(final String dest, final float price) 4 { 5 return new Destination() 6 { 7 private int cost; 8 { 9 cost = Math.round(price); 10 if(cost > 100) 11 System.out.println("Over budget"); 12 } 13 private String lable = dest; 14 public String readLable() { return lable; } 15 }; 16 } 17 public static void main(String[] args) 18 { 19 Parcel10 p = new Parcel10(); 20 Destination d = p.destination("Tasmaina", 101.395F); 21 } 22 }
其中 destination 的參數必須是 final 的,由於他們在匿名類中被使用到了。
在實例初始化的內部,有 if 語句,它們不能做爲實例初始化動做的一部分。因此對於匿名類而言,實例初始化的實際效果就是構造器。(可是,你不能重載實例初始化方法,因此僅有一個這樣的構造器)
匿名內部類與正規繼承相比是受到限制的,由於匿名內部類既能夠擴展類,也能夠實現接口,可是不能兩者兼備。而且,若是是實現接口,也只能實現一個接口。