You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java序列化读写.ser文件时HashMap出现重复管理员条目问题排查

问题根因

  1. Credentials类toString方法实现不符合预期:你生成HashMap存储键时使用的是Encryption.SHA_512(credentials.toString()),如果Credentials类没有重写toString方法,会默认调用Object类的原生实现,输出格式为类名@内存地址哈希值。每次应用运行时新创建的Credentials对象内存地址不同,toString输出结果就不同,对应的SHA512哈希值每次都不一样。这就导致插入前的键存在性校验永远不命中,每次都会生成新的键插入管理员数据,看起来就是重复的管理员条目。
  2. selectUser方法逻辑和插入逻辑不匹配:initAdmin的插入判断用的是selectUser(admin.getCredentials())==null,而你的HashMap键是Credentials的哈希字符串,如果selectUser方法没有先把传入的Credentials参数转成对应的SHA512哈希再查询,而是直接用Credentials对象作为键查询String类型键的HashMap,永远会返回null,也会导致每次都走插入逻辑。
  3. (次要优化点)read方法存在冗余异常:空文件时直接创建ObjectInputStream读取会固定抛出EOFException,属于可提前规避的异常。

修复方案

  • 重写Credentials类的toString方法,保证相同账号密码的Credentials对象输出的字符串完全一致,也可以单独写getKey()方法返回拼接的账号密码作为哈希源,避免后续toString逻辑被修改影响存储:
// Credentials类新增代码
@Override
public String toString() {
    return "Credentials{username='" + username + "', password='" + password + "'}";
}
  • 修正selectUser方法逻辑,和insert逻辑对齐,先转哈希再查询:
public User selectUser(Credentials credentials) throws NoSuchAlgorithmException {
    if (credentials == null) return null;
    String hash = Encryption.SHA_512(credentials.toString());
    return users.get(hash);
}
  • (可选优化)修改read方法,提前判断空文件避免不必要的异常抛出:
public Object read() {
    Object obj = null;
    File temp = new File(this.filename);
    try {
        // 空文件直接返回null,不用读取
        if (!temp.exists() || temp.length() == 0) {
            temp.createNewFile();
            return null;
        }
        try (FileInputStream fileIn = new FileInputStream(temp);
             ObjectInputStream objectIn = new ObjectInputStream(fileIn)) {
            obj = objectIn.readObject();
        }
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
    return obj;
}

内容的提问来源于stack exchange,提问作者laegil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:54:05