背景
在java中,存在4種引用關係,但是4種引用關係也有一些差異,這裏主要討論若引用和虛引用,但是一些細節點討論:
- API上有什麼不同 ?
- 虛引用和弱引用有什麼不同?如果都是GC時都被回收,爲什麼不使用虛引用呢 ?
- 引用實例的強引用釋放之後,有什麼不同?
解答:
- 但是在gc上,他們很類似,但有有些區別,java 8.0之前,虛引用持有對象可能無法釋放,因爲爲了通知對象將要被回收,虛引用會標記對象是激活狀態,導致無法回收,java 8之後幾乎完全一樣,虛引用通知對象被回收在虛引用回收之後。
- 產生時期不同
那麼既然 java 8之後虛引用會被回收,爲什麼不使用虛引用而使用弱引用呢 ?
主要原因是虛引用的api決定了,get() 返回值是null
使用注意事項
常量:
不要使用虛引用引用常量 (基本類型+字面量字符串),因爲常量的生命週期相對較長
靜態成員:
不要引用靜態成員,Class,因爲這類成員生命週期也是很長
局部變量:
不要引用局部變量,局部變量引用如果是異步+callback方式,很容易因爲內存問題,導致局部變量提前被釋放,造成不可控風險。
public static void main(String[] args){
final Logger log = new Logger("HaHaha");
testHttp(new WeakReference(log))
}
public void testHttp(WeakReference<Logger> ref){
okHttpClient.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) {
e.printStackTrace();
Logger log = ref.get(); //log可能提前爲空
}
@Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
Logger log = ref.get(); //log可能提前爲空
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
Headers responseHeaders = response.headers();
for (int i = 0, size = responseHeaders.size(); i < size; i++) {
System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
}
System.out.println(responseBody.string());
}
}
});
}
}