今天下午写代码,遇到了一个这样的场景:
子类继承父类,父类的函数代码逻辑,子类可以不需要修改逻辑,直接拿来用就行。但是父类的函数代码逻辑里使用到一些静态变量,继承该父类的子类需要对这些静态变量进行重写,但是由于方法是在父类里的,子类直接调用父类的方法,仍然是使用父类的那些静态变量。
我一想,这不就是反射的应用场景嘛..于是,一下子撸了一个出来。示例代码如下:
- 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"));
}
}
执行结果如下:
我本来觉得这样已经达到效果,但是带我的师傅却说,用反射性能太低了。
后来讨论了一番,将代码修改成了如下:
- 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());
}
}
执行结果如下:
方法其实就是:
- 将静态属性转换为非静态属性,并且去掉final;
- 子类对象初始化时修改父类对象的值。