内部类也叫做嵌套类,在 Java 中是一个被大家经常使用到的东西。内部类除了匿名内部类外还分为三种:一种是可以被独立构造实例且和外部类完全剥离的静态内部类,一种是可以自由访问外部类成员变量和方法的成员内部类,一种是作用域和生命周期都只处在一个方法中的方法内部类,但这种内部类我们不讨论。
在 Kotlin 中,内部类默认是静态内部类,只有用 inner
修饰符声明静态内部类,才能让 Kotlin 中默认的静态内部类变为非静态的成员内部类。
1 静态内部类
Kotlin 中,类可以嵌套。一个类可以嵌套在其他类中,而且可以嵌套多层。
1 | class NestedClass { |
测试代码如下:
1 | val one = NestedClass.Outer().one |
可以看出,代码中 NestedClass.Outer.Inner().getTwo() 访问嵌套类的方式是直接使用类名.来访问,有多少层嵌套,就用多少层类名来访问。
普通嵌套类没有持有外部类的引用,所以是无法访问外部类变量的:
1 | class NestedClass { |
2 成员内部类
如果一个类 Inner 想要访问外部类 Outer 中的成员,可以在这个类前面添加修饰符 inner。内部类会带有一个对外部类的对象引用。
1 | class NestedClass { |
1 | NestedClass.Outer().Inner().accessOuter() |
可以看到,当访问嵌套内部类 Inner 的时候,我们使用的是 Outer().Inner(),这是持有了 Outer 的对象引用,与普通嵌套类直接使用类名访问的方式不同。
3 匿名内部类
匿名内部类就是没有名字的内部类。匿名内部类也可以访问外部类的变量。下面使用对象表达式创建一个匿名内部类实例:
1 | class NestedClass { |
如果对象是函数式 Java 接口,即具有单个抽象方法的 Java 接口的实例,例如上面例子中的 Runnable 接口:
1 | // Java 8 中引入的函数式接口注解 |
我们可以使用 Lambda 表达式实现 Runnable 接口。下面的几种写法都是可以的:
1 | fun doStop() { |