在分析内存泄漏
领域的问题时,时常会提到的就是非静态内部类持有外部类的引用导致的内存泄漏,因为内部类持有了外部类的引用,导致垃圾回收器无法回收外部类对象,久而久之就会存在内存泄漏的隐患。
我们在使用非静态内部类的时候,并不是说我们不手动编码引用外部类对象属性就不存在引用关系,实际上这层关系是通过隐式引用来实现的。
静态内部类持有外部类的引用
我们写一个非静态内部类对象示例:
/**
* @author imyzt
* @date 2024/05/13
* @description 非静态内部类,匿名持有外部类的引用
*/
public class NonStaticInnerClazz {
private final String name;
public NonStaticInnerClazz(String name) {
this.name = name;
}
public class Inner {
public void print() {
System.out.println(name);
}
}
}
可以看到javac之后的代码中,第九行方法形参将外部类NonStaticInnerClazz
传入给了内部类的this.this$0
属性进行引用。
非静态内部类无法引用外部类的属性
而非静态内部类则没有这种情况。
/**
* @author imyzt
* @date 2024/05/13
* @description 静态内部类,无法引用外部类的属性
*/
public class StaticInnerClazz {
private final String name;
public StaticInnerClazz(String name) {
this.name = name;
}
public static class Inner2 {
public void print2() {
// Non-static field 'name' cannot be referenced from a static context
// System.out.println(name);
}
}
}
其他非静态内部类引用的情况
而其他非静态内部类的情况也有类似的问题:
编写测试类:
/**
* @author imyzt
* @date 2024/05/13
* @description 描述信息
*/
public class NonStaticFieldClazz {
// 成员变量-匿名内部类的非static实例
private Inner3 inner3_1 = new Inner3() {
private Integer field_111;
};
// 成员变量-非静态内部类的非static实例
private Inner3 inner3_2 = new Inner3();
public void print() {
// 局部变量-匿名内部类的非static实例
Inner3 inner3_3 = new Inner3() {
private Integer field_333;
};
// 局部变量-非静态内部类的非static实例
Inner3 inner3_4 = new Inner3();
}
public class Inner3 {
}
}
1. 成员变量-匿名内部类的非static实例
class NonStaticFieldClazz$1 extends NonStaticFieldClazz.Inner3 {
private Integer field_111;
NonStaticFieldClazz$1(NonStaticFieldClazz var1) {
super(var1);
this.this$0 = var1;
}
}
2. 局部变量-匿名内部类的非static实例
class NonStaticFieldClazz$2 extends NonStaticFieldClazz.Inner3 {
private Integer field_333;
NonStaticFieldClazz$2(NonStaticFieldClazz var1) {
super(var1);
this.this$0 = var1;
}
}
3. 局部变量和成员变量的非static内部类的非static实例
public class NonStaticFieldClazz$Inner3 {
public NonStaticFieldClazz$Inner3(NonStaticFieldClazz var1) {
this.this$0 = var1;
}
}