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 语句,它们不能做为实例初始化动做的一部分。因此对于匿名类而言,实例初始化的实际效果就是构造器。(可是,你不能重载实例初始化方法,因此仅有一个这样的构造器)
匿名内部类与正规继承相比是受到限制的,由于匿名内部类既能够扩展类,也能够实现接口,可是不能两者兼备。而且,若是是实现接口,也只能实现一个接口。