将Client类存入HashMap后读取出现空值,求技术排查
问题概述
开发小型银行账户管理系统时,将Client实例存入HashMap后无法正确读取,打印客户信息时出现空值,且HashMap存储逻辑存在混乱。
相关代码片段
System.out.println("this has been created "); JOptionPane.showMessageDialog(f, "Account registered successfully"); System.out.println("***********************************"); System.out.println("account registered " + bank.clientMap.get(userId) +" "+ bank.getLoginInfo()); System.out.println("user details " + client.getName()+" "+ client.getUsername() +" " + client.getAddress() +" "+ client.getBalance());
输出信息
Client Account Created
this has been created
account registered com.xbank.event.Client@52605789 {50.0=com.xbank.event.Client@52605789, Pass_123=com.xbank.event.Client@52605789, 115 High Road=com.xbank.event.Client@52605789, Admin=com.xbank.event.Client@52605789, user123=com.xbank.event.Client@52605789}
user details null 50.0
核心问题分析
1. Client类Getter方法实现错误
getAddress()无参方法直接返回null,导致打印地址时必然为空:public String getAddress() { return null; }getPassword(String password)和getAddress(String address)属于冗余错误方法,传入参数直接返回,未读取对象自身属性。
2. HashMap存储逻辑混乱
在Bank_Account.addInfo()中,将同一个Client实例用多个非唯一键(密码、地址、姓名、余额)重复存入HashMap:
clientMap.put(newClient.getUsername(), newClient); clientMap.put(newClient.getPassword(password), newClient); clientMap.put(newClient.getAddress(address), newClient); clientMap.put(newClient.getName(), newClient); clientMap.put(Double.toString(newClient.getBalance()), newClient);
这种设计会导致:
- 键的含义完全错误,HashMap应使用唯一标识(如用户名)作为键
- 若存在属性值相同的用户,后存入的实例会覆盖前一个,造成数据丢失
3. 打印逻辑使用错误实例
打印user details时使用的client对象,并非从HashMap中取出的实例,而是未正确初始化的对象,导致getName()、getUsername()返回空值。
4. Client类未重写toString()
打印Client实例时输出默认的哈希值(com.xbank.event.Client@52605789),无法直观查看对象属性,不利于调试。
5. Static HashMap引发数据共享问题
clientMap被定义为static,所有Bank_Account实例会共享同一个HashMap,易引发并发问题或数据混乱。
修复方案
1. 修正Client类Getter方法
删除冗余的带参Getter,保留正确的无参Getter:
public String getAddress() { return this.address; } public String getPassword() { return this.password; }
2. 规范HashMap存储逻辑
仅使用唯一标识(如用户名)作为键存入HashMap:
// 仅保留这一行,用用户名作为唯一键 clientMap.put(newClient.getUsername(), newClient);
若需通过其他属性查找用户,遍历HashMap的值进行筛选即可,无需把所有属性作为键。
3. 确保打印使用HashMap中的实例
修改打印代码,直接使用从HashMap取出的对象:
Client storedClient = bank.clientMap.get(userId); System.out.println("account registered " + storedClient + " " + bank.getLoginInfo()); System.out.println("user details " + storedClient.getName() + " " + storedClient.getUsername() + " " + storedClient.getAddress() + " " + storedClient.getBalance());
4. 重写Client类toString()方法
方便调试时查看对象属性:
@Override public String toString() { return "Client{" + "name='" + name + '\'' + ", username='" + username + '\'' + ", address='" + address + '\'' + ", balance=" + balance + ", accNum='" + accNum + '\'' + '}'; }
5. 移除HashMap的Static修饰符
// 修改Bank_Account类中的定义 public HashMap<String, Client> clientMap; // 构造方法初始化 public Bank_Account() { clientMap = new HashMap<String, Client>(); } // 同步修改getLoginInfo()方法为非static public Map<String, Client> getLoginInfo() { return clientMap; }
内容的提问来源于stack exchange,提问作者sillyconAdmin

