java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...
當(dāng)我們分析內(nèi)存泄漏的場景時(shí),總會(huì)想到不能在內(nèi)部類中做耗時(shí)操作,因?yàn)樗鼤?huì)持有外部類的因?yàn)?導(dǎo)致外部類的實(shí)例在生命周期結(jié)束的時(shí)候沒有辦法及時(shí)釋放,這就造成了內(nèi)存泄漏.
好像這就是一個(gè)公理一樣,就是人們說著說著就都認(rèn)可它了,卻沒有人能說出個(gè)為什么.
今天我們就來分析一下為什么吧
首先來看一個(gè)例子
public class Outer {
private int count;
//匿名內(nèi)部類1
private StaticInner si1 = new StaticInner(){
@Override
public void doAction() {
count++;
}
};
private StaticInner si2;
private Inner i3;
public void setInner(StaticInner inner) {
this.si2 = inner;
}
public Outer() {
i3 = new Inner();
//匿名內(nèi)部類2
setInner(new StaticInner(){
@Override
public void doAction() {
super.doAction();
count++;
}
});
}
public void doAction() {
si1.doAction();
si2.doAction();
i3.doSomething();
}
/**
* 內(nèi)部類
*/
private class Inner {
public void doSomething() {
count++;
}
}
/**
* 靜態(tài)內(nèi)部類
*/
private static class StaticInner{
public void doAction() {
}
}
}
以上代碼概述了我們平時(shí)寫代碼時(shí)常見的幾種內(nèi)部類和匿名內(nèi)部類以及靜態(tài)內(nèi)部類的寫法,并訪問了外部類的成員變量,當(dāng)然靜態(tài)內(nèi)部類沒法訪問,編譯器會(huì)報(bào)錯(cuò).
然后通過javac命令編譯一下.java源文件,得到幾個(gè).class字節(jié)碼文件,這時(shí)如果你嘗試打開字節(jié)碼文件,會(huì)發(fā)現(xiàn)一堆亂碼,可以用jd-gui字節(jié)碼反編譯工具打開.
我們可以發(fā)現(xiàn)好幾個(gè).class文件,一個(gè)一個(gè)來看
Outer$1.class
class Outer$1
extends Outer.StaticInner
{
Outer$1(Outer paramOuter)
{
super(null);
}
public void doAction()
{
Outer.access$108(this.this$0);
}
}
這個(gè)類代表我們聲明成員變量si1的匿名內(nèi)部類,可以看到它繼承自靜態(tài)內(nèi)部類StaticInner,它還定義了一個(gè)構(gòu)造函數(shù),并傳入了內(nèi)部類的實(shí)例作為參數(shù),雖然不知道super(null)具體實(shí)現(xiàn),但是我們知道它要訪問paramOuter實(shí)例的成員變量,必須得使用它的引用來訪問,所以它肯定是持有了外部類實(shí)例的引用.
Outer$2.class
class Outer$2
extends Outer.StaticInner
{
Outer$2(Outer paramOuter)
{
super(null);
}
public void doAction()
{
super.doAction();
Outer.access$108(this.this$0);
}
}
這個(gè)和上面提到的Outer$1.class類似,所以這兩種匿名內(nèi)部類是沒有任何本質(zhì)區(qū)別的,不管是定義成員變量還是方法傳參.
Outer$Inner.class
class Outer$Inner
{
private Outer$Inner(Outer paramOuter) {}
public void doSomething()
{
Outer.access$108(this.this$0);
}
}
這是定義的內(nèi)部類,可以看到編譯器也為它單獨(dú)生成了一個(gè).class文件,構(gòu)造函數(shù)被定義為私有的,且同樣傳入了外部類的實(shí)例,所以它也是持有了外部類實(shí)例的引用.
Outer$StaticInner.class
class Outer$StaticInner
{
public void doAction() {}
}
這是靜態(tài)內(nèi)部類編譯后的字節(jié)碼文件,編譯器并沒有為它添加額外的構(gòu)造函數(shù),所以它其實(shí)和我們的外部類沒有任何關(guān)系,這是寫在同一個(gè).java源文件中而已.
分析到這里,應(yīng)該算可以證明為什么靜態(tài)內(nèi)部類會(huì)持有外部類的實(shí)例了
在分析內(nèi)存泄漏的時(shí)候,它應(yīng)該是我們應(yīng)該重點(diǎn)關(guān)注的對象.
由此我們也能夠明白java代碼執(zhí)行過程并不是我們所看的那樣,編譯器也做了很多工作.只是這一塊我們并不怎么關(guān)注.
總結(jié)
以上是生活随笔為你收集整理的java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java redis释放连接_redis
- 下一篇: java实现doc向swf格式的转换 转