Kotlin 内部类

Posted by OOFTF Blog on April 25, 2021

内部类

通过字节码分析内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ExternalClass {
    fun go(){
    }
    fun test() {
        object :View.OnClickListener{
            override fun onClick(v: View?) {

            }
        }
    }
    fun test2() {
        object :View.OnClickListener{
            override fun onClick(v: View?) {
                go()
            }
        }
    }
    inner class InternalClass(int: Int) {

    }
}

查看字节码,这不是原始字节码,删除了一些不必要信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public final class com/ooftf/myapplication/ExternalClass {

  public final go()V

  public final test()V

  public final test2()V


  public <init>()V

  public final INNERCLASS com/ooftf/myapplication/ExternalClass$InternalClass com/ooftf/myapplication/ExternalClass InternalClass
  public final static INNERCLASS com/ooftf/myapplication/ExternalClass$test$1 null null

  public final static INNERCLASS com/ooftf/myapplication/ExternalClass$test2$1 null null
}

public final class com/ooftf/myapplication/ExternalClass$InternalClass {


  public <init>(Lcom/ooftf/myapplication/ExternalClass;I)V

  final synthetic Lcom/ooftf/myapplication/ExternalClass; this$0

  public final INNERCLASS com/ooftf/myapplication/ExternalClass$InternalClass com/ooftf/myapplication/ExternalClass InternalClass
}

public final class com/ooftf/myapplication/ExternalClass$test$1 implements android/view/View$OnClickListener {

  OUTERCLASS com/ooftf/myapplication/ExternalClass test ()V
  public onClick(Landroid/view/View;)V
  <init>()V
  public final static INNERCLASS com/ooftf/myapplication/ExternalClass$test$1 null null
}

public final class com/ooftf/myapplication/ExternalClass$test2$1 implements android/view/View$OnClickListener {

  OUTERCLASS com/ooftf/myapplication/ExternalClass test2 ()V
  public onClick(Landroid/view/View;)V

  <init>(Lcom/ooftf/myapplication/ExternalClass;)V

  final synthetic Lcom/ooftf/myapplication/ExternalClass; this$0

  public final static INNERCLASS com/ooftf/myapplication/ExternalClass$test2$1 null null
}

分析字节码:

非静态内部类

ExternalClass$InternalClass 是非静态内部类,查看字节码可知,在构造方法中添加了一个参数 该参数的类型为当前类 ExternalClass。

匿名内部类

ExternalClass$test$1 和 ExternalClass$test2$1 都是匿名内部类但是其构造方法不同: ExternalClass$test$1 的构造方法是没有参数的,而 ExternalClass$test2$1 的构造方法是以 ExternalClass 作为参数的,这是因为 ExternalClass$test2$1 调用了 ExternalClass.go 方法。因此我们可以认为编译器会智能判断匿名内部类是否需要将外部类作为参数传递到内部类中。也就是说匿名内部类不一定会持有外部类的引用