Java父类如何统一处理子类实例变量写入JSONObject
问题解答
子类变量对父类的可见性
子类实例变量能否被父类访问,完全由访问修饰符决定:
private修饰:父类完全无法访问,这是Java封装特性的基本规则。protected/public修饰:父类可以直接访问,但这种写法会破坏封装,不推荐使用。- 默认包访问权限(无修饰符):仅同包的父类能访问,跨包则不行。
能不能遍历子类实例变量写入JSON?
可以实现,但不推荐用反射硬做——反射虽能获取子类所有字段,但会绕过封装规则,代码可读性、维护性差,还容易因字段修改出现同步问题。
更优雅的解决方案
方案1:抽象方法让子类提供专属字段
在父类Activity中定义抽象方法,让子类实现该方法返回自身专属字段的键值对,父类统一处理写入逻辑,既遵守封装又避免代码重复:
// 父类Activity public abstract class Activity { // 原有字段与逻辑... public void createActivity() { File file = database; JSONObject newActivity = new JSONObject(); setRegDate(LocalDate.now()); try { actID = IO.getJsonArray(file, "Activities").length() + 1; } catch (Exception e) { System.out.println("Exception: Could not set new activity ID."); } // 写入父类字段 newActivity.put("userID", userID); newActivity.put("actDate", actDate); newActivity.put("regDate", regDate); newActivity.put("actID", actID); newActivity.put("description", description); newActivity.put("coach", coach); // 写入子类专属字段 Map<String, Object> extraFields = getExtraFields(); for (Map.Entry<String, Object> entry : extraFields.entrySet()) { newActivity.put(entry.getKey(), entry.getValue()); } try { IO.putObjInArr(file, newActivity, "Activities"); } catch (Exception e) { System.out.println("Exception: Creating activity failed."); } } // 抽象方法,子类实现 protected abstract Map<String, Object> getExtraFields(); } // 子类示例 public class RunningActivity extends Activity { private double distance; private long time; @Override protected Map<String, Object> getExtraFields() { Map<String, Object> fields = new HashMap<>(); fields.put("distance", distance); fields.put("time", time); return fields; } }
方案2:用JSON序列化库自动处理
直接使用Jackson、Gson这类成熟的JSON库,它们能自动识别父类与子类的所有字段(只要有getter或通过注解指定),序列化时自动打包所有字段为JSON,无需手动拼接:
public void createActivity() { File file = database; setRegDate(LocalDate.now()); try { actID = IO.getJsonArray(file, "Activities").length() + 1; } catch (Exception e) { System.out.println("Exception: Could not set new activity ID."); } // 直接序列化当前对象(子类实例会自动包含子类字段) Gson gson = new Gson(); String jsonStr = gson.toJson(this); JSONObject newActivity = new JSONObject(jsonStr); try { IO.putObjInArr(file, newActivity, "Activities"); } catch (Exception e) { System.out.println("Exception: Creating activity failed."); } }
这种方案最省心,字段增删改只需修改实体类,推荐优先使用。
你提出的HashMap方案
你的思路是可行的,但可以优化为上述抽象方法的形式,让子类主动提供字段而非父类被动接收,代码结构更清晰,也符合面向对象设计原则。
内容的提问来源于stack exchange,提问作者Ontkibbeling
相关产品推荐
相关产品推荐

