似乎像下面這樣的簡單擴展屬性不起作用。
var Dog.age = 0;
推薦的實作方式是什么?我已經嘗試了以下方法,它有效,但這會阻止Dog垃圾收集器清理任何物件,不是嗎?
class Dog
{
}
val dogAgeMap=HashMap<Dog, Int>();
var Dog.age:Int
get() = dogAgeMap[this]?: 0;
set(value){ dogAgeMap[this] = value}
class PetShop
{
fun work()
{
val d1 = Dog();
d1.age = 100;
val d2 = Dog();
d2.age = 200;
println("${d1.age}, ${d2.age}");
}
}
fun main(args:Array<String>)
{
PetShop().work();
}
uj5u.com熱心網友回復:
正確,這將防止呼叫 setter的Dog實體在定義age的范圍內被 GC dogAgeMap。如果您在有限的范圍內定義了Dog.age擴展屬性(因此dogAgeMap),并且生命周期有限(短),那么您就可以了。
但是,如果不是這種情況,并且您需要age整個應用程式中的所有資訊,那么age應該只是原始類定義的一部分,并且您永遠不會遇到這個問題。
這種情況下的解決方案
class Dog(val age: Int)
如果你需要的age只是在你的應用程式的一部分資訊,然后更好的方法是創建查找(中HashMap),只為那一部分,或者簡單地使用,帶有濃郁的類age(或包裝類age),而不是的Dog類在您的應用程式的那一部分。當您完成那里的作業時,您會清理地圖或豐富的類實體。這樣,任何實體都不會泄漏。
但是如果你真的想在整個應用程式中使用擴展屬性,因此你需要一直保持對的參考dogAgeMap,那么如果你有很多實體,你需要注意記憶體泄漏經歷并設定他們的年齡。
如果這是您的情況,您可以使用 aWeakHashMap<Dog, Int>代替。AWeakHashMap只保留弱參考,它不會阻止Dog實體被 GC(一旦你的強參考不再保留)。
import java.util.WeakHashMap
val dogAgeMap = WeakHashMap<Dog, Int>()
var Dog.age: Int
get() = dogAgeMap[this] ?: 0
set(value) {
dogAgeMap[this] = value
}
但是請注意,這WeakHashMap是一個 Java 類,而不是 Kotlin 核心庫的一部分,因此如果您將 Kotlin 用于多平臺,這將不起作用。在這種情況下,您需要WeakHashMap在每個平臺上都有一個實作(庫)。
如果您的狗資料還包含每只狗的 ID,則另一種方法是使用 ID 作為查找鍵。這將有可能移植到所有平臺。然后實施將更改為
// I am using a Long here, but it could be whatever type that
// is small enough to not cause memory concerns, since
// these keys would still exist in memory because a normal HashMap is used.
class Dog(val id: Long) {}
val dogAgeMap = HashMap<Long, Int>()
var Dog.age: Int
get() = dogAgeMap[id] ?: 0
set(value) {
dogAgeMap[id] = value
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/406224.html
標籤:
