日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...

發布時間:2024/10/6 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當我們分析內存泄漏的場景時,總會想到不能在內部類中做耗時操作,因為它會持有外部類的因為,導致外部類的實例在生命周期結束的時候沒有辦法及時釋放,這就造成了內存泄漏.

好像這就是一個公理一樣,就是人們說著說著就都認可它了,卻沒有人能說出個為什么.

今天我們就來分析一下為什么吧

首先來看一個例子

public class Outer {

private int count;

//匿名內部類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();

//匿名內部類2

setInner(new StaticInner(){

@Override

public void doAction() {

super.doAction();

count++;

}

});

}

public void doAction() {

si1.doAction();

si2.doAction();

i3.doSomething();

}

/**

* 內部類

*/

private class Inner {

public void doSomething() {

count++;

}

}

/**

* 靜態內部類

*/

private static class StaticInner{

public void doAction() {

}

}

}

以上代碼概述了我們平時寫代碼時常見的幾種內部類和匿名內部類以及靜態內部類的寫法,并訪問了外部類的成員變量,當然靜態內部類沒法訪問,編譯器會報錯.

然后通過javac命令編譯一下.java源文件,得到幾個.class字節碼文件,這時如果你嘗試打開字節碼文件,會發現一堆亂碼,可以用jd-gui字節碼反編譯工具打開.

我們可以發現好幾個.class文件,一個一個來看

Outer$1.class

class Outer$1

extends Outer.StaticInner

{

Outer$1(Outer paramOuter)

{

super(null);

}

public void doAction()

{

Outer.access$108(this.this$0);

}

}

這個類代表我們聲明成員變量si1的匿名內部類,可以看到它繼承自靜態內部類StaticInner,它還定義了一個構造函數,并傳入了內部類的實例作為參數,雖然不知道super(null)具體實現,但是我們知道它要訪問paramOuter實例的成員變量,必須得使用它的引用來訪問,所以它肯定是持有了外部類實例的引用.

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);

}

}

這個和上面提到的Outer$1.class類似,所以這兩種匿名內部類是沒有任何本質區別的,不管是定義成員變量還是方法傳參.

Outer$Inner.class

class Outer$Inner

{

private Outer$Inner(Outer paramOuter) {}

public void doSomething()

{

Outer.access$108(this.this$0);

}

}

這是定義的內部類,可以看到編譯器也為它單獨生成了一個.class文件,構造函數被定義為私有的,且同樣傳入了外部類的實例,所以它也是持有了外部類實例的引用.

Outer$StaticInner.class

class Outer$StaticInner

{

public void doAction() {}

}

這是靜態內部類編譯后的字節碼文件,編譯器并沒有為它添加額外的構造函數,所以它其實和我們的外部類沒有任何關系,這是寫在同一個.java源文件中而已.

分析到這里,應該算可以證明為什么靜態內部類會持有外部類的實例了

在分析內存泄漏的時候,它應該是我們應該重點關注的對象.

由此我們也能夠明白java代碼執行過程并不是我們所看的那樣,編譯器也做了很多工作.只是這一塊我們并不怎么關注.

總結

以上是生活随笔為你收集整理的java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。