第10章--内部类_匿名内部类
public interface Contents{ int value();} public class Parcel7{ public Contents contents() { //借助于Contents接口,创建一个匿名内部类的唯一实例 //该实例必须要 实现 借助的 接口Contents return new Contents() { private int i = 11; public int value() { TT(); return i; } //改方法只能在匿名内部类内部使用 public void TT() { } }; //这个分号不能少 } public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents c = p.contents(); }}
?2. 借助于 常规类的 构造函数 生成匿名内部类的唯一对象
? ?这种方式生成的内部类,其实相当于把协助生成匿名内部类唯一对象的
? ?那个常规类当成一个接口来使用(可以使用常规类的public方法),同时生成的匿名内部类唯一实例可以使用
? ?那个常规类的protected方法以及friend方法(方法前面什么都不加).
? ?但是匿名内部类自己内部新增的public方法 不能被使用,所以这中方式 与继承也不用.
? ?介于 实现接口和继承之间.
? ?
? ?//协助生成内部类唯一对象的 常规类?
?
public class Wrapping{ private int i; public Wrapping(int x) { i = x; } public int value() { return i; } //protected方法 protected void testProtected() { System.out.println("testProtected()"); } //friend 方法 void testFriend() { System.out.println("testFriend()"); } static void testStatic() { System.out.println("testStatic()"); }}
?当做返回值的匿名内部类.
public class Parcel8{ public Wrapping wrapping(int x) { // 通过借助常规类的构造函数方法实现的匿名内部类,介于继承和实现接口之间: return new Wrapping(x) //匿名内部类 的对象 要么作为 方法返回值; 要么作为方法的参数; //这样 匿名内部类 总是作为一个已知的类的子类 或者 已知接口的实现类(这里 都涉及到向上转型) //所以 创建匿名内部类 的语法 总是 new 基类() {类定义} 或 new 接口() {类定义} //匿名内部类 不可能有构造器(因为匿名内部类没有名字) 所以匿名内部类只能使用 默认构造器来创建对象 { // Pass constructor argument. public int value() { return super.value() * 47; } }; // Semicolon required } public static void main(String[] args) { Parcel8 p = new Parcel8(); Wrapping w = p.wrapping(10); w.testFriend(); //什么都不加的方法 w.testProtected(); //protected方法 w.testStatic(); //静态方法 }} /*** 这里必须要传递一个参数x给构造函数的原因* 1. 如果 类一个参数构造器都没有,则编译器会自动加一个默认构造器(即无参构造器)* 2. 假如 类 已经有一个构造器,则编译器不会再自动加上默认构造器* 3. 导出类的构造器必须首先要调用基类的构造器,* 如果基类没有默认构造器(比如 上面的Wrapping 只有一个构造器Wrapping(int x)),* 则导出类的构造器必须首先要显式的调用基类的构造器,因此上面内部类定义时必须传入参数x给* 基类的构造器Wrapping(int x)* * 总之,如果导出类的构造器没有首先显式的调用基类的构造器,则编译器会自动让导出类调用基类的默认* 构造器,如果基类没有默认构造器,则导出类必须首先显式的调用基类的其他构造器,否则编译不通过.*/
?3. 匿名内部类中直接使用了外部的对象,比如定义匿名内部类的函数的参数,那么这个参数必须是final的.
public class Parcel9{ private int iTmp = 3; public Destination destination(final String dest) { return new Destination() { private String label = dest; //局部内部类直接使用了 函数的参数,则参数必须为final的. public int iTmpInner = iTmp; //局部内部类使用 外围类 字段 iTmp, iTmp 不 需要 是final的(内部类中自动拥有外围类的引用) public String readLabel() { iTmpInner++; return label; } }; } public static void main(String[] args) { Parcel9 p = new Parcel9(); Destination d = p.destination("Tasmania"); }}
?4. 匿名内部类没有构造函数,可以使用初始化块完成初始化.
?
? ?下面的例子中,传递给匿名内部类的参数i 不需要 是final的,因为i没有直接在匿名内部类中使用,
? ?而是传递给匿名内部类的基类使用.
abstract class Base{ public Base(int i) { System.out.println("Base constructor, i = " + i); } public abstract void f();}public class AnonymousConstructor{ public static Base getBase(int i) { return new Base(i) //参数i 不需要 是final的,因为i没有直接在匿名内部类中使用, //而是传递给匿名内部类的基类使用. { private int cost; { cost = 100;//匿名内部类, 初始化块中的初始化, System.out.println("Inside instance initializer"); } public void f() { System.out.println("In anonymous f()"); } public void g() //匿名内部类,继承了基类,即使自己新增了一个方法g(),返回的唯一的匿名内部类的对象也无法使用这个新增的方法 //所以,匿名内部类的继承 其实 相当于实现接口 { System.out.println("In anonymous g()"); } }; } public static void main(String[] args) { Base base = getBase(47); base.f(); }}
?