java:非静态内部类中的Filed:this$0

java:非静态内部类中的Filed:this$0

1 前言

通过反射方法getDeclaredFields()获取类Class的全部字段时,会发现内部类(非静态)的字段中,存在父类的实例字段,修饰为final,属性名为this$0。若此非静态内部类需要调用父类的实例方法,那么使用parent class.this即可。

2 使用

public class TestFields {

    public static void main(String[] args) {

        new TestFields().new Fruit().run();

        System.out.println(Arrays.toString(getAllDeclaredFieldList(Fruit.class)));

        System.out.println(Arrays.toString(Fruit2.class.getDeclaredFields()));

        System.out.println(Arrays.toString(Fruit3.class.getDeclaredFields()));

    }

    private void run(){
        System.out.println("TestFields run");
    }

    @ToString
    @Data
    private class Fruit{
        String fruitName;

        // 使用 parent class.this可调用父类实例方法
        public void run(){
            TestFields.this.run();
        }
    }

    @ToString
    @Data
    private static class Fruit2{
        String fruitName;

    }

    public static Field[] getAllDeclaredFieldList(Class<?> clazz){
        Field[] allFieldList = null;
        do{
            Field[] declaredFields = clazz.getDeclaredFields();
            allFieldList = ArrayUtils.addAll(allFieldList, declaredFields);
            clazz = clazz.getSuperclass();
        }while(clazz != null && !clazz.equals(Object.class));

        return allFieldList;
    }

}

@ToString
@Data
class Fruit3{
    String fruitName;
}

执行结果如下:

TestFields run
[java.lang.String xiaoxu.project.TestFields$Fruit.fruitName, 
final xiaoxu.project.TestFields xiaoxu.project.TestFields$Fruit.this$0]
[java.lang.String xiaoxu.project.TestFields$Fruit2.fruitName]
[java.lang.String xiaoxu.project.Fruit3.fruitName]

会发现非静态的内部类Fruit中,全部字段除了fruitName外,还具有final 修饰的this$0变量,该变量为父类TestFields实例对象,而静态内部类Fruit2中则没有该变量。

可以反射获取this$0变量对象,一般不需如此操作。若非静态内部类Fruit中需要使用父类TestFields的实例方法,如下使用TestFields.this亦可:

@ToString
@Data
private class Fruit{
    String fruitName;

    // 使用 parent class.this可调用父类实例方法
    public void run(){
        TestFields.this.run();
    }
}

最后,若希望getAllDeclaredFieldList方法不会获取到非静态内部类中的this$0字段,简单增加如下过滤即可:

public static Field[] getAllDeclaredFieldList(Class<?> clazz){
    Field[] allFieldList = null;
    do{
        Field[] declaredFields = clazz.getDeclaredFields();

        Field[] fields = Arrays.stream(declaredFields)
                .filter(field -> !("this$0".equals(field.getName())
                        && Modifier.isFinal(field.getModifiers())))
                .toArray(new IntFunction<Field[]>() {
                    @Override
                    public Field[] apply(int value) {
                        return new Field[value];
                    }
                });

        allFieldList = ArrayUtils.addAll(allFieldList, fields);
        clazz = clazz.getSuperclass();
    }while(clazz != null && !clazz.equals(Object.class));

    return allFieldList;
}

过滤了非静态内部类中的this$0父类实例Field,再次执行结果如下:

TestFields run
[java.lang.String xiaoxu.project.TestFields$Fruit.fruitName]
[java.lang.String xiaoxu.project.TestFields$Fruit2.fruitName]
[java.lang.String xiaoxu.project.Fruit3.fruitName]

另外非静态内部类中不含有无参构造方法,建议需要反射调用newInstance()方法时,使用public定义的实体类。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值