開発で弱参照について学ぶ機会があったので、忘れないように記録しておきます。
自分なりに嚙み砕いて解説しています。
強参照と弱参照とは?
お察しの通り、強いつながりのある参照と弱いつながりのある参照です。
強参照:通常の参照です。”=”でオブジェクトを参照します。
弱参照:WeakReference<>()でオブジェクトを参照します。
実際には、ほかにも色々あるのですが
詳しく知りたい方はこちらを参照してください
https://qiita.com/wbspry/items/daa5c844647604e27e4f
実際に見てみるとこんな感じです。
class SmapleObject(){
}
//強い参照
strongRef = SmapleObject()
//弱い参照
weakRef = WeakReference<SmapleObject>(strongRef)
なんかややこしいですよね。
私もそう思います。
図で表すとこんな感じです
strongRefは直接、SmapleObject型のオブジェクトを参照しています。
WeakRefは、WeakReference< SmapleObject >を使用し、引数にあるstrongRefの参照しているオブジェクトを参照しています。(「弱到達が可能なオブジェクト」)
一応ここまでは、同じオブジェクトを参照していることにはなります。
次にstrongRefをnullで初期化します。
strongRef = SmapleObject()
weakRef = WeakReference<SmapleObject>(strongRef)
//nullにする
strongRef = null
strongRefの参照先が変わっただけで、weakRefは変わらず、WeakReferenceで元のオブジェクトを見ています。
実際ここまでは違いがあまり分からないと思うのですが、
この参照の大きな違いは、ガーベジ・コレクタ(GC)の対象になるかどうかということです。
ガーベジ・コレクタ(GC)
ガーベージ・コレクタ(Garbage Collector)は、プログラミング言語や実行環境が自動的にメモリを解放するための仕組みの一つです。
Androidの実行環境もJavaの実行環境を基にしており、Java Virtual Machine (JVM) におけるガーベージ・コレクタの仕組みを利用しています。
明示的に起こすものではなく、自動的に起きるので扱いが難しいのが現状です。
GCが行われるとどこからも(メンバ変数やメソッド)参照されていないオブジェクトは、解放されます。
強参照しているオブジェクトは解放されません。
しかし、弱参照が参照しているオブジェクトは参照していることにはされずGCの対象になります。
実際にGCを起こして、見ると参照関係がどうなるか見てみましょう。
strongRef = SmapleObject()
weakRef = WeakReference<SmapleObject>(strongRef)
strongRef = null
//GCする
System.gc()
SmapleObject型のオブジェクトは、 WeakReferenceしか参照していないためメモリ解放の対象となります。
sampleObject2 = weakRef.get()//null
まとめ
強参照:参照をし続ける限りGCの対象にならない
→メモリを圧迫する可能性がある(解放には、参照を外す必要がる)
弱参照:参照をし続けてもGCの対象になる
→自動的に開放されるのでメモリを圧迫しずらい
最後に
弱参照って初めて聞きました。。。
ちょっと面白いですね。