【Java / Kotlin】Warning:Leaking ‘this‘ in constructor of non-final class

14 篇文章 1 订阅

在构造函数(注意:init 块和给成员变量(属性)赋初值的语句,都是构造函数的一部分)中使用 this 时,可能会出现这个警告。如果不理会,可能导致访问到未初始化的成员变量。Java 中,它们可以是未赋初值或赋值为 null 的引用类型;Kotlin 中,可以是 lateinit var 或未赋值或赋值为 null 的可空类型。
事实上,在构造函数中使用 this,即便这个类是 final 的(Kotlin 中则为没有 open 修饰的类),也有可能导致这样的后果。这主要发生在将 this 作为参数(实参)传递给其它函数,或者添加到 Array 之类的情形中。在这些条件下,其它函数可以通过这个引用访问到该类的公有成员。然而,在使用 this 这一行的语句之后,可以还有其它语句;又或者,这条语句是调用了其它函数,在这个被调用的函数里完成了传递 this 引用或将其添加到数组之类的动作。很显然,这一瞬间,构造函数还没有执行完毕(没有返回)。在多线程的条件下,如果其它函数可以使用 this 引用(比如,在添加到 ArrayList 后,就立即通过条件变量的 notify 操作通知其它线程,这些线程继续执行的时候,通过这个引用,访问该类的实例),那么,它们就有可能在该类的实例的构造函数未完成的时候,访问到尚未被初始化的成员,进而 NullPointerException。此外,并不是在构造函数的最后一条语句里才这么做就万事大吉。为了提升性能,语句(指令)的顺序是可以被重排的。也就是说,在函数本体中,最后才出现的语句不一定是最后才被执行的。
如果这个类还有子类,更有可能出现这样的后果。通常,会在子类的构造函数中调用父类的构造函数。父类的构造函数将 this 暴露给其它函数的时候,子类还没有构造完毕。其它函数可以通过这个 this 引用,访问到子类的成员。而这些成员里,自然有可能存在一些尚未初始化的成员。
当然,毕竟这只是一个警告。如果置之不理,还是能通过编译的。假使实在需要这样做,也并不是不行。不过,如果产生了 NullPointerException,且异常点所在的类存在子类,或程序是多线程的;并且涉及的这些类的代码中存在这样的警告,则可以考虑往这个方面排查原因。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin中,`java.lang.NullPointerException: null cannot be cast to non-null type`是一个常见的运行时错误,它发生在尝试将null值转换为非空类型(如引用类型)时。这是因为Kotlin是一种强类型语言,它不允许你对可能为null的对象执行非空类型的操作。 当你遇到这个错误时,通常意味着你在代码的某个地方尝试调用了一个方法或访问了一个属性,而该对象在运行时是null。例如: ```kotlin val myObject: MyNonNullClass? = null // 声明一个可为null的对象 myObject?.doSomething() // 这里会抛出异常,因为doSomething()期望myObject不为null // 或者在访问属性时 val myValue = myObject?.myProperty // 如果myObject为null,myProperty会被视为null,尝试访问会导致异常 ``` 解决这个问题的方法有几种: 1. 在调用或访问前进行安全检查:使用`?.`(safe call operator)来防止null安全问题,如果对象为null,表达式将返回null,不会抛出异常。 ```kotlin if (myObject != null) { myObject.doSomething() } ``` 2. 使用`also`扩展函数:当需要执行一些操作但不关心是否为null时,可以在null安全上下文中使用`also`。 ```kotlin myObject?.also { it.doSomething() } ``` 3. 初始化变量或方法参数时设置默认值:如果不确定值是否为null,可以在声明时设置默认值。 ```kotlin val myObject = myObject ?: MyNonNullClass() // 如果myObject为null,创建一个新的MyNonNullClass实例 ``` 4. 使用可空类型(nullable types):如果你确实希望某个变量可以是null,那么声明时使用`MyNonNullClass?`而不是`MyNonNullClass`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值