Java内部类持有外部类的引用详细分析与解决方案

来源:互联网 发布:淘宝商家数量统计 编辑:程序博客网 时间:2024/04/29 12:33

在Java中内部类的定义与使用一般为成员内部类与匿名内部类,他们的对象都会隐式持有外部类对象的引用,影响外部类对象的回收。

GC只会回收没有被引用或者根集不可到达的对象(取决于GC算法),内部类在生命周期内始终持有外部类的对象的引用,造成外部类的对象始终不满足GC的回收条件,反映在内存上就是内存泄露。(如,Android中Activity的内存泄露)

解决方案为

1.将内部类定义为static

2.用static的变量引用匿名内部类的实例或将匿名内部类的实例化操作放到外部类的静态方法中

测试代码

class Outer {    class Inner {        public String publicString = "Inner.publicString";    }    Other anonymousOther = new Other() {        public String publicString = "Anonymous Other.publicString";    };    public Other getAnonymousOther() {        return anonymousOther;    }    Other Other = new Other();    public Other getOther() {        return Other;    }}class Other {    public String publicString = "Other.publicString";}

调用代码

public static void main(String args[]) {        printField(new Outer().new Inner());        System.out.println("\t");        printField(new Outer().getAnonymousOther());        System.out.println("\t");        printField(new Outer().getOther());    }

测试结果

Class: at.miao.Outer$Inner变量: publicString 值为 Inner.publicString变量: this$0 值为 at.miao.Outer@456c5f50Class: at.miao.Outer$1变量: publicString 值为 Anonymous Other.publicString变量: this$0 值为 at.miao.Outer@10e80317Class: at.miao.Other变量: publicString 值为 Other.publicString

可以看到内部类与匿名内部类的实例都有一个外部类类型的名为this$0的变量指向了外部类的对象。

加上static之后,代码为

class Outer {    static class Inner {        public String publicString = "Inner.publicString";    }    static Other anonymousOther = new Other() {        public String publicString = "Anonymous Other.publicString";    };    public Other getAnonymousOther() {        return anonymousOther;    }    Other Other = new Other();    public Other getOther() {        return Other;    }}class Other {    public String publicString = "Other.publicString";}

调用代码

public static void main(String args[]) {        printField(new Outer.Inner());        System.out.println("\t");        printField(new Outer().getAnonymousOther());        System.out.println("\t");        printField(new Outer().getOther());    }

测试结果

Class: at.miao.Outer$Inner变量: publicString 值为 Inner.publicStringClass: at.miao.Outer$1变量: publicString 值为 Anonymous Other.publicStringClass: at.miao.Other变量: publicString 值为 Other.publicString

可以看到静态内部类实例、static引用的匿名内部类的实例未引用外部类的实例。

将匿名内部类的实例化操作放到外部类的静态方法中也可以达到上述效果:

public static Other getAnonymousOther() {        return new Other() {            public String publicString = "Anonymous Other.publicString";        };    }

调用代码

printField(Outer.getAnonymousOther());

采用静态化的方式不一定是最好的解决方案,请根据业务需要以及代码优化需要选择。

2 1
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 红米note3屏幕裂了怎么办 小米3屏幕烂了怎么办 苹果x屏幕触屏不灵怎么办 票买好了身份证丢了怎么办 广发信用卡身份证到期了怎么办 人在外地身份证丢了怎么办 人在国外身份证丢了怎么办 身份证丢了户口本不在怎么办 在北京身份证过期了怎么办 没社保卡怎么办厦门健康卡 扬州市民卡丢了怎么办 扬州市民卡坏了怎么办 重庆社保卡坏了怎么办 社保卡丢了看病怎么办 社保卡丢了买药怎么办 常州社保卡丢了怎么办 深圳社保卡掉了怎么办 上海医保卡丢了怎么办 户口转到西安后医保怎么办 上海医保卡掉了怎么办 上海医保本丢了怎么办? 新版医保卡丢了怎么办 武汉社保卡掉了怎么办 职工社保卡丢了怎么办 杭州社保卡丢了怎么办 农村医疗卡丢了怎么办 陕西省医保卡丢了怎么办 小孩社保卡掉了怎么办 社区医保本丢了怎么办 宝宝医保卡掉了怎么办 同煤医疗卡丢了怎么办 杭州医保卡丢了怎么办 新的医保卡丢了怎么办 二代医保卡丢了怎么办 老医保卡丢了怎么办 上海医保卡余额用完了怎么办 身份证丢了医疗报销怎么办 取公积金身份证丢了怎么办 身份证丢了怎么办就诊卡 人在外地怎么办农村社保卡 武汉医保卡丢了怎么办