Java的内部类很有趣。你可以这样定义一个内部类:
- class Outer {
- class Inner {}
- }
Inner是必须与某一个Outer对象绑定的,通过外部创建内部类的方法就可以得知:
- Outer oo = new Outer();
- Outer::Inner ii = oo.new Inner();
所以每一个Inner都有对应的一个外部类对象,而且内部类可以访问外部类对象中的所有属性和方法,包括private权限的。内部类可以用Outer.this来得到外部类对象的引用:
- class Outer {
- class Inner {
- Outer GetOuter()
- {
- return Outer.this;
- }
- }
- }
在方法中或一个作用域“{}”中也可以定义内部类,用一段比较变态的代码来说明问题:
- class Outer {
- int a = 6
- class Inner {
- int b = 3;
- void f()
- {
- class FunInner { // class defined in a funciton!!
- int sum()
- {
- return a + b; // Outer.a + Inner.b
- }
- }
- FunInner fi = new FunInner();
- System.out.print(fi.sum()); // 9!!
- }
- }
- }
还有一种东西叫“匿名内部类”:
- interface I {
- void f();
- }
- class Outer {
- I getI()
- {
- return new I() { // anonymous inner class !!
- public void f() {}
- };
- }
- }
如果不需要和外部类绑定,可以定义一个嵌套类:
- class Outer {
- static class Nested {} // static
- }
嵌套类和C++中的嵌套类基本相同,只能访问外部类的静态数据。它的创建方法为:
- Outer.Nested nested = new Outer.Nested();
接口里面也可以定义嵌套类,但不需要static修饰,因为接口里定义的变量都是默认为public static的:
- interface I {
- void f();
- class MyI implements I {
- void void f() {}
- }
- }
这样做的好处是接口的定义同时还能提供默认的实现。
内部类的作用:
内部类可以继承别的类,同时又可以完全访问外部类的成员,这就等同于多重继承的效果。
Java里没有指针,所以不能像C++一样把函数指针传递给出去作为回调函数(callback)。通过内部类可以实现:
- interface Callback { void call(); }
- class MyClass {
- void f() {} // want to be a callback
- Callback getCallback()
- {
- return new Callback() {
- void call() { f(); }
- };
- }
- }
- class Caller {
- void operation(Callback callback)
- {
- callback.call();
- }
- static void main(String[] args)
- {
- Caller caller = new Caller();
- MyClass mc = new MyClass();
- caller.operation(mc.getCallback());
- }
- }
Java中的这样的回调机制叫做
闭包(closure)。
内部类也可以被继承。因为外部类和内部类有着千丝万缕的联系,所以继承的类同样需要某种机制建立起这种联系:
- class Outer { class Inner{} }
- public class InheritInner extends Outer.Inner {
- // InheritInner() {} // compile error!
- InheritInner(Outer oo) {
- oo.super(); // It's a must to connect to the outer class
- }
- static void main(String[] args)
- {
- Outer oo = new Outer();
- InheritInner ii = new InheritInner(oo);
- }
- }
内部类同样会生成.class文件,它的文件名会是这样的形式:Outer$Inner.class。如果是匿名内部类,在$后会简单加入一个数字作为标识符。
阅读(828) | 评论(0) | 转发(0) |