创建内部类
如果想从外部类的非静态方法之外的地方创建某个内部类的对象:具体的指明类型:OuterClassName.InnerClassName
链接到外部类
内部类能访问制造它的外部类的所有成员,拥有其外围类**所有元素(包括private)**的访问权。例如:迭代器
.this
生成外部类对象的引用:OuterClassName.this
.new
外部类要创建某个非静态内部类的对象:
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
想要直接创建内部类对象,必须使用外部类对象来创建。
嵌套类(静态内部类)
嵌套类不需要对外部对象的引用,在不需要内部类对象与外围类对象之间有联系时,可以使用嵌套类,即将内部类声明为static 。
普通内部类不能有static字段和方法,也不能包含嵌套类,但嵌套类可以包含这些东西。
接口内部可以放置嵌套类,如果想创建某些公共代码使它们可以被某个接口所有不同实现所共用,可以使用接口内部嵌套类。
例如,需要在每个类中都有一个main函数来测试一个方法:
public class TestBed {
public void f() { System.out.println("f()");}
public static class Tester {
public static void main(String[] args) {
TestBed t = new TestBed();
t.f();
}
}
}
生成了一个独立的类 TestBed$Tester(要运行这个程序 执行java TestBed$Tester
即可)
内部类与向上转型
内部类向上转型为基类或接口。
在方法和作用域内的内部类
- 定义在方法中的类
- 定义在作用域中的类
- 实现了接口匿名类
- 扩展了有非默认构造器的类的匿名类
- 执行字段初始化的匿名类
- 通过实例初始化实现构造的匿名类
匿名内部类
- 匿名内部类使用外部对象,则外部对象应该是final的
- 匿名内部类不可能有命名构造器,构造器的行为可以通过实例初始化实现,如
abstract class Base { public Base(int i) { print("Base constructor, i = " + i); } public abstract void f(); } public class AnonymousConstructor { public static Base getBase(int i) { return new Base(i) { {print("Inside instance initializer");} public void f() { print("In anonymous f()"); } }; } }
实例初始化的效果就是构造器,但不能重载实例初始化方法,最多有一个实例初始化
使用内部类的好处
- 内部类可以有多个实例,每个实例有自己的状态信息,并且与其外围类对象的信息相互独立
- 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类
- 创建内部类对象的时刻并不依赖于外围类对象的创建
- 内部类就是一个独立的实体
闭包与回调
控制框架
继承内部类
指向外围类对象的引用必须被初始化,导出类中不再存在可连接的默认对象。必须在构造器内使用
encloszingClassReference.super(); //显式调用构造函数
内部类的覆盖
无法直接覆盖,但可以通过引用覆盖
局部内部类
不能有访问控制符,可以访问当前代码块的常量和外围类的所有成员
内部类标识符
OuterClassName$InnerClassName.class
tips
- 匿名类不能有构造器