Java內部類持有外部類的引用詳細分析與解決方案


Java中內部類的定義與使用一般為成員內部類與匿名內部類,他們的對象都會隱式持有外部類對象的引用,影響外部類對象的回收。

GC只會回收沒有被引用或者根集不可到達的對象(取決於GC算法),內部類在生命周期內始終持有外部類的對象的引用,造成外部類的對象始終不滿足GC的回收條件,反映在內存上就是內存泄露。(如,Android中Activity的內存泄露)

解決方案為

1.將內部類定義為static

2.用static的變量引用匿名內部類的實例

測試代碼

[java] view plain copy
  1. class Outer {  
  2.     class Inner {  
  3.         public String publicString = "Inner.publicString";  
  4.     }  
  5.   
  6.     Other anonymousOther = new Other() {  
  7.         public String publicString = "Anonymous Other.publicString";  
  8.     };  
  9.     public Other getAnonymousOther() {  
  10.         return anonymousOther;  
  11.     }  
  12.   
  13.     Other Other = new Other();  
  14.     public Other getOther() {  
  15.         return Other;  
  16.     }  
  17. }  
  18.   
  19. class Other {  
  20.     public String publicString = "Other.publicString";  
  21. }  

調用代碼

[java] view plain copy
  1. public static void main(String args[]) {  
  2.         printField(new Outer().new Inner());  
  3.         System.out.println("\t");  
  4.         printField(new Outer().getAnonymousOther());  
  5.         System.out.println("\t");  
  6.         printField(new Outer().getOther());  
  7.     }  

 

測試結果

[plain] view plain copy
  1. Class: at.miao.Outer$Inner  
  2. 變量: publicString 值為 Inner.publicString  
  3. 變量: this$0 值為 at.miao.Outer@456c5f50  
  4.       
  5. Class: at.miao.Outer$1  
  6. 變量: publicString 值為 Anonymous Other.publicString  
  7. 變量: this$0 值為 at.miao.Outer@10e80317  
  8. Class: at.miao.Other  
  9. 變量: publicString 值為 Other.publicString  


可以看到內部類與匿名內部類的實例都有一個外部類類型的名為this$0的變量指向了外部類的對象。

加上static之后,代碼為

[java] view plain copy
  1. class Outer {  
  2.     static class Inner {  
  3.         public String publicString = "Inner.publicString";  
  4.     }  
  5.   
  6.     static Other anonymousOther = new Other() {  
  7.         public String publicString = "Anonymous Other.publicString";  
  8.     };  
  9.   
  10.     public Other getAnonymousOther() {  
  11.         return anonymousOther;  
  12.     }  
  13.   
  14.     Other Other = new Other();  
  15.     public Other getOther() {  
  16.         return Other;  
  17.     }  
  18. }  
  19.   
  20. class Other {  
  21.     public String publicString = "Other.publicString";  
  22. }  

調用代碼

[java] view plain copy
  1. public static void main(String args[]) {  
  2.         printField(new Outer.Inner());  
  3.         System.out.println("\t");  
  4.         printField(new Outer().getAnonymousOther());  
  5.         System.out.println("\t");  
  6.         printField(new Outer().getOther());  
  7.     }  

 

測試結果

[java] view plain copy
  1. Class: at.miao.Outer$Inner  
  2. 變量: publicString 值為 Inner.publicString  
  3.       
  4. Class: at.miao.Outer$1  
  5. 變量: publicString 值為 Anonymous Other.publicString  
  6.       
  7. Class: at.miao.Other  
  8. 變量: publicString 值為 Other.publicString  

可以看到靜態內部類實例、static引用的匿名內部類的實例未引用外部類的實例。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM