Java如何在父类方法中访问子类的static静态属性?
问题根因
输出为null的核心原因是Java的静态属性不存在重写机制,父类method方法中引用的var_name在编译期就已经绑定到父类的静态属性,和子类的同名静态属性属于完全无关的两个变量,因此调用父类方法时只会读取父类的null值。
可选替代方案
方案1:抽象getter方法(最推荐,无性能损耗,改造成本极低)
不需要重写整个method方法,只需要在父类定义抽象取值方法,每个子类实现该方法返回对应的值即可,单个子类仅需新增3行以内代码,远比重写整个method成本低:
abstract class SuperClass { // 定义抽象取值方法 abstract String getVarName(); void method(){ // 直接调用实例方法取值,动态绑定到子类实现 System.out.println(getVarName()); } } class SubClass extends SuperClass { private static final String VAR_NAME = "I need to print this"; // 仅需实现这个getter即可,不需要改method逻辑 @Override String getVarName() { return VAR_NAME; } void otherUnrelatedMethod(){ method(); // 此时输出为子类的VAR_NAME值 } }
优点:无额外性能损耗、类型安全、符合Java面向对象设计规范,改造成本极低。
方案2:泛型+反射缓存(适配必须保留静态变量声明的场景)
如果业务要求必须保留子类的静态var_name声明,可以用泛型绑定子类类型,同时缓存反射获取的字段值,避免每次调用都反射带来的性能损耗:
import java.util.concurrent.ConcurrentHashMap; import java.lang.reflect.Field; abstract class SuperClass<S extends SuperClass<S>> { static String var_name = null; // 缓存子类静态字段值,避免重复反射 private static final ConcurrentHashMap<Class<?>, String> VAR_CACHE = new ConcurrentHashMap<>(); void method(){ String value = VAR_CACHE.computeIfAbsent(this.getClass(), clazz -> { try { Field field = clazz.getDeclaredField("var_name"); field.setAccessible(true); return (String) field.get(null); } catch (Exception e) { // 兜底返回父类值 return var_name; } }); System.out.println(value); } } class SubClass extends SuperClass<SubClass> { static String var_name = "I need to print this"; void otherUnrelatedMethod(){ method(); // 首次调用反射获取值并缓存,后续直接走缓存 } }
优点:不需要修改现有子类的静态变量声明,缓存后性能损耗可忽略;缺点:存在少量反射改造工作量,字段名写错时只有运行时才能发现问题。
方案3:父类构造传入配置值
如果子类的var_name都是固定值,可以在父类构造时要求传入对应值,存到父类的实例属性中,method直接读取实例属性即可:
abstract class SuperClass { private final String varName; // 父类构造要求传入配置值 protected SuperClass(String varName) { this.varName = varName; } void method(){ System.out.println(varName); } } class SubClass extends SuperClass { private static final String VAR_NAME = "I need to print this"; // 子类构造时传入自身的静态值即可 public SubClass() { super(VAR_NAME); } void otherUnrelatedMethod(){ method(); // 直接输出子类传入的值 } }
优点:无性能损耗、类型安全,改造量同样很小。
内容的提问来源于stack exchange,提问作者João Schmidt
相关产品推荐
相关产品推荐

