可以将一个类的定义放在另一个类的定义内部,这就是内部类。
内部类分成静态内部类和非静态内部类, 非静态内部类有额外两种特殊形式, 一种叫局部类, 另一种叫匿名内部类.同时, 我们把包裹内部类的类称为外围类(外部类)。
静态内部类除了访问权限修饰符比外围类多以外, 和外围类没有区别, 只是代码上将静态内部类组织在了外围类里面. 如果在外围类外部引用静态内部类, 需要带上外围类的名字。
非静态内部类和静态内部类不同, 非静态内部类能访问外围类的一切成员, 包括私有成员, 就好像它确实是在外围类的里面, 能看到外围类这个黑盒内部的细节.
而很容易被忽视的一点是, 外部类虽然不能直接访问内部类的成员, 但是可以通过内部类的实例访问, 注意, 外部类 能访问 非静态内部类私有成员.
如果想在外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须使用 OuterClassName.InnerClassName 。
在内部类中使用外部类的对象, OuterClass.this
创建内部类对象, OuterClass oc = new OuterClass(); OuterClass.Inner in = oc.new Inner();
由于非静态内部类不能脱离外围类实例单独存在, 它 不能 有static成员. static成员是和类相关的, 不和实例相关, 而非静态内部类必须依赖一个实例才能存在, 所以它不能有static成员也是很容易理解的.
当然我这里说的static成员, 除了一种, 那就是 static final
形式的 常量 . 很奇怪吧, 非静态内部类竟然允许定义常量, 事实确实是这样.
非静态内部类里面不能定义接口, 因为接口是隐式static的.
另外静态初始化块也是不允许出现在非静态内部类中的.
匿名内部类可以看成是一种没有名字的局部类, 它可以让我们的类的定义和实例化同时进行。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
匿名内部类的定义和实例化往往是在一条语句里完成的, 所以我们会看到匿名内部类的最后面还会有一个分号.
匿名内部类的访问外部变量的规则和局部类相同.
匿名内部类不能定义构造方法, 这很容易理解, 因为连类名都没有, 构造方法连名字都不知道, 更别提定义了.
下面是匿名内部类的例子(Peron可以是类也可以是接口)
abstract class Person { public abstract void eat(); } public class Demo { public static void main(String[] args) { Person p = new Person() { public void eat() { System.out.println("eat something"); } }; p.eat(); } }
关注我的公众号获取更多内容