当前位置: 首页 > Thinking in Java > 正文
第10章–内部类_匿名内部类
Jul222013
作者:边城网事 发布:2013-07-22 08:45 分类:Thinking in Java 阅读:1,045 抢沙发
匿名内部类,因为没有名字,所以不可能有构造方法.
因而,匿名内部类一般就只有一个实例.
匿名内部类,只能借助于接口或者其他常规类的构造函数来实现.
匿名内部类通常作为函数的返回值或者参数.
1. 借助于接口实现的匿名内部类
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(); } }
赞 赏
微信赞赏 支付宝赞赏
本文固定链接: https://www.jack-yin.com/coding/thinking-in-java/2360.html | 边城网事