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

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

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

解決方案爲測試

1.將內部類定義爲staticthis

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

測試代碼對象

  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. }  

調用代碼生命週期

  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.     }  

 

測試結果內存

  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的變量指向了外部類的對象。get

加上static以後,代碼爲string

  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. }  

調用代碼

  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.     }  

 

測試結果

  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引用的匿名內部類的實例未引用外部類的實例。

相關文章
相關標籤/搜索