今天下午写代码,遇到了一个这样的场景:

子类继承父类,父类的函数代码逻辑,子类可以不需要修改逻辑,直接拿来用就行。但是父类的函数代码逻辑里使用到一些静态变量,继承该父类的子类需要对这些静态变量进行重写,但是由于方法是在父类里的,子类直接调用父类的方法,仍然是使用父类的那些静态变量。

我一想,这不就是反射的应用场景嘛..于是,一下子撸了一个出来。示例代码如下:

  • Father:
@Service
public class Father {

    private static final String NAME = "FATHER";

    public String getStaticFiledValueByName(String fieldName) {
        String fieldValue = "NONE";
        try {
            Class<? extends Father> clazz = this.getClass();
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            if (field.getType().toString().endsWith("java.lang.String") && Modifier.isStatic(field.getModifiers())) {
                fieldValue = (String) field.get(this.getClass());
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return fieldValue;
    }

    public String getName() {
        return NAME;
    }
}
  • Children
@Service
public class Children extends Father {

    private static final String NAME = "CHILDREN";
  
}
  • Test代码
@SpringBootTest
class YangliziTestApplicationTests {

    @Autowired
    private Father father;

    @Autowired
    private Children children;

    @Test
    void contextLoads() {

        System.out.println(father.getStaticFiledValueByName("NAME"));
        System.out.println(children.getStaticFiledValueByName("NAME"));
    }
}

执行结果如下:

alt

我本来觉得这样已经达到效果,但是带我的师傅却说,用反射性能太低了。

后来讨论了一番,将代码修改成了如下:

  • Father
@Service
public class Father {

    protected String NAME = "FATHER";

    public String getName() {
        return NAME;
    }
}
  • Children
@Service
public class Children extends Father {

    private String NAME = "CHILDREN";

    @PostConstruct
    void init() {
        super.NAME = this.NAME;
    }
}
  • test代码
@SpringBootTest
class YangliziTestApplicationTests {

    @Autowired
    private Father father;

    @Autowired
    private Children children;

    @Test
    void contextLoads() {

        System.out.println(father.getName());
        System.out.println(children.getName());

        // 再打印1次父类的
        System.out.println(father.getName());
    }
}

执行结果如下: alt

方法其实就是:

  1. 将静态属性转换为非静态属性,并且去掉final;
  2. 子类对象初始化时修改父类对象的值。