Java非静态内部类属性this$0

问题

在日常写代码的时候,发现递归获取类属性值的过程中出现堆栈溢出。单步调试之后发现,是由于非静态内部类的this$0属性引起的。下面我们对this$0展开研究。

研究

首先定义如下类结构,作为实验对象。

public class User {
    private String userName;
    private SubUser subUser;
    private StaticSubUser staticSubUser;

    public User(String userName) {
        this.userName = userName;
        this.subUser = new SubUser("subUserName");
        this.staticSubUser = new StaticSubUser("staticSubUserName");
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    public SubUser getSubUser() {
        return subUser;
    }

    public class SubUser{
        private String subUserName;

        public SubUser(String subUserName) {
            this.subUserName = subUserName;
        }

        public String getSubUserName() {
            return subUserName;
        }

        public void setSubUserName(String subUserName) {
            this.subUserName = subUserName;
        }
    }

    public static class StaticSubUser{
        private String staticSubUserName;

        public StaticSubUser(String staticSubUserName) {
            this.staticSubUserName = staticSubUserName;
        }

        public String getStaticSubUserName() {
            return staticSubUserName;
        }

        public void setStaticSubUserName(String staticSubUserName) {
            this.staticSubUserName = staticSubUserName;
        }
    }
}

通过单步调试,可以很容易发现,非静态内部类有一个指向外部类实例的属性this$0,而静态内部类没有这个属性,如下图所示:
在这里插入图片描述

这个属性在反射获取属性的时候是可以被获取到的,会导致无限递归,最终导致堆栈溢出。但是在代码层面上我们无法使用这个this$0属性,若需要在非静态内部类中获取外部类实例,可以使用User.this,注意静态内部类不允许这种用法。

    public class SubUser{
    ...
        public User getUser(){
            return User.this;
        }
    }

可以看到我们成功拿到了外部类示例
在这里插入图片描述

解决

通过将非静态内部类修改为静态内部类,问题得到解决。

《Effective Java》书中也有建议:

Item 24: Favor static member classes over nonstatic
优先考虑使用静态成员类

写在最后

很喜欢某个博主的一句话:你知道的越多,不知道的越多。加油!冲!冲!冲!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值