面试:内部类为什么会持有外部类的引用

问题1:内部类为什么会持有外部类的引用

这是因为内部类虽然和外部类写在同一个文件中,但是编译后还是会生成不同的class文件,其中内部类的构造函数中会传入外部类的实例,然后就可以通过this$0访问外部类的成员。

其实也挺好理解的吧,因为在内部类中可以调用外部类的方法,变量等等,所以肯定会持有外部类的引用的。

贴一段内部类在编译后用JD-GUI查看的class代码,也许你能更好的理解:

//原代码
class InnerClassOutClass{

    class InnerUser {
       private int age = 20;
    }
}

//class代码
class InnerClassOutClass$InnerUser {
    private int age;
    InnerClassOutClass$InnerUser(InnerClassOutClass var1) {
        this.this$0 = var1;
        this.age = 20;
     }
}

问题2:kotlin中的内部类与Java有什么不一样吗

这是因为在kotlin中的匿名内部类分为两种情况:

  • 在Kotlin中,匿名内部类如果没有使用到外部类的对象引用时候,是不会持有外部类的对象引用的,此时的匿名内部类其实就是个静态匿名内部类,也就不会发生内存泄漏。
  • 在Kotlin中,匿名内部类如果使用了对外部类的引用,像我刚才使用了btn2,这时候就会持有外部类的引用了,就会需要考虑内存泄漏的问题。
//java,匿名内部类的写法
btn.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {

    }
});

 上面这个是java匿名内部类的写法,kotlin没有new关键字,那么kotlin的匿名内部类该怎么写呢?

btn.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        print("1111")
    }
})

同样kotlin中对于内部类也是和Java有区别的:

  • Kotlin中所有的内部类都是默认静态的,也就都是静态内部类
  • 如果需要调用外部的对象方法,就需要用inner修饰,改成和Java一样的内部类,并且会持有外部类的引用,需要考虑内存泄漏问题。

kotlin的内部类与java的内部类有点不同java的内部类可以直接访问外部类的成员,kotlin的内部类不能直接访问外部类的成员,必须用inner标记之后才能访问外部类的成员 

  • 没有使用inner标记的内部类
class A{
    var a = 0
    class B{
        //B类的内部是不能直接用a变量的
        var b = 1
    }
}
  •  用inner标记的内部类
class A{
    var a = 0
    inner class B{
        //B类的内部可以直接用a变量
        var b = a
    }
}

反编译后的java代码

public final class A {
   private int a;

   public final int getA() {
      return this.a;
   }

   public final void setA(int var1) {
      this.a = var1;
   }

   public final class B {
      private int b = A.this.getA();

      public final int getB() {
         return this.b;
      }

      public final void setB(int var1) {
         this.b = var1;
      }
   }
}

从上面可以看出,没有使用inner标记的内部类最后生成的是静态内部类,而使用inner标记的生成的是非静态内部类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值