Возможность утечки памяти вызвана тем фактом, что каждый экземпляр класса inner
содержит ссылку на экземпляр внешнего класса.Этот экземпляр внешнего класса может не понадобиться логике программы, но он все еще видим и, следовательно, не подлежит сборке мусора.
Итак, если вы знаете, что экземпляр вложенного классаможет не потребоваться все содержимое экземпляра внешнего класса для его логики, вы можете убедиться в отсутствии утечек памяти, не используя inner
классы.
Если вам все еще нужны некоторые части экземпляра внешнего класса, выможно передать эти значения экземпляру вложенного класса вручную:
class A {
val b: B = someB()
val c: C = someC()
// D uses C but does not need B, so we pass C to the constructor:
class D(private val c: C) { /* ... */ }
fun createD(): D = D(c)
}
Если вам также нужен экземпляр вложенного класса, чтобы наблюдать изменения свойства экземпляра внешнего класса (а не просто использовать моментальный снимок свойства во вложенном классе).время создания экземпляра класса), вы можете вручную обернуть это свойство в держатель ссылки и передать его в конструктор вложенного класса:
class A {
val b: B = someB()
private val cHolder = CHolder(someC())
class CHolder(var c: C)
var c: C
get() = cHolder.c
set(value) { cHolder.c = value }
// D uses C but does not need B, so we pass C to the constructor:
class D(private val cHolder: CHolder) { /* ... */ }
fun createD(): D = D(cHolder)
}
Вместо класса CHolder
может потребоватьсяиспользуйте какое-то общее решение, если этот шаблон повторяется в вашем коде;это всего лишь демонстрация.
Тогда, если вы хотите сослаться на весь экземпляр внешнего класса, есть возможность передать его конструктору вложенного класса.По сравнению с inner class
это позволяет вам вручную управлять временем жизни внешнего экземпляра и удалять ссылку на него, когда он не нужен:
class A {
class D(private var outer: A?) {
fun forgetOuterInstance() {
outer = null
}
}
fun createD(): D = D(this)
}
И, наконец, если вашему вложенному классу нужен внешний классэкземпляра в течение всего времени его существования, или если внешний класс не содержит дорогих ресурсов, и вы можете иметь дело с потенциально более длинным временем жизни его экземпляров, тогда можно использовать inner class
, просто имейте в виду, что экземпляр внешнего классаостанется в живых до тех пор, пока это делает экземпляр внутреннего класса.В связи с этим вы можете захотеть переместить некоторые ресурсы из внешнего класса для хранения и выпустить их более детально.