Java程序Map.get返回null触发空指针异常修复方案
问题根因定位
程序运行抛出的异常如下:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.Map.equals(Object)" because the return value of "java.util.Map.get(Object)" is null
at week21.03.Search2(03.java:69)
at week21.03.main(03.java:48)
抛出空指针的直接原因是Search2方法的Map操作逻辑完全错误,具体问题点如下:
- 外层
Final是Map<String,Map<String,String>>类型,它的key是存储时传入的公司名称(字符串类型),不存在整数类型的key。原代码用for循环遍历整数i,再调用Final.get(i)永远拿不到对应值,只会返回null。 - 原代码直接在外层Map上调用
Final.get("Name")/Final.get("Mail")这类方法完全错误:"Name"、"Mail"是内层每个名片Map的key,外层Map根本没有这些key,调用get必然返回null,后续直接调用equals()方法就触发了空指针。 - 代码还存在其他隐藏bug:
- 创建了两个Scanner对象读取同一个标准输入流,且调用
nextInt()后没有处理残留的换行符,会导致后续nextLine()读取到空字符串,输入逻辑错位 - 存储手机号时内层Map用的key是
"Number",搜索时却写的"Phone number",key不匹配会导致手机号永远搜不到 Search方法没有判断公司名不存在的场景,用户输入不存在的公司名时同样会触发空指针- 定义的
data1类全程没有被使用,属于冗余代码
- 创建了两个Scanner对象读取同一个标准输入流,且调用
修复方案
按以下步骤修改即可解决问题:
- 重写
Search2的遍历逻辑:HashMap没有整数索引,要遍历外层Map的entrySet拿到每一条公司-名片的键值对,再从内层名片Map中匹配字段 - 统一字段key的命名,保证存储和搜索时的key完全一致
- 所有Map取值后先做非空判断,key不存在时给出提示,不要直接调用对象方法
- 只保留一个Scanner实例,每次调用
nextInt()后追加一次nextLine()吞掉输入流里残留的换行符,避免输入错位 - 删除未使用的冗余
data1类
修复后完整代码
package week21; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class _03_ { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int o1 = 0; Map<String, Map<String, String>> finalMap = new HashMap<>(); while (o1 != 3) { System.out.println("What would you like to do:"); System.out.println("1. Add"); System.out.println("2. Search"); System.out.println("3. Exit"); o1 = scanner.nextInt(); scanner.nextLine(); // 吞掉nextInt残留的换行 if(o1 == 1){ Map<String,String> save = new HashMap<>(); System.out.println("Name of owner:"); String name = scanner.nextLine(); save.put("Name", name); System.out.println("Email:"); String mail = scanner.nextLine(); save.put("Mail", mail); System.out.println("Phone number:"); String nr = scanner.nextLine(); save.put("Number", nr); System.out.println("Address:"); String address = scanner.nextLine(); save.put("Address", address); System.out.println("Name of company:"); String cName = scanner.nextLine(); finalMap.put(cName, save); } else if (o1 == 2) { System.out.println("What would you like to do:"); System.out.println("1. A piece of information"); System.out.println("2. Everything about a company"); System.out.println("3. Everything"); int o = scanner.nextInt(); scanner.nextLine(); if (o == 1) { searchSingleField(finalMap, scanner); } else if (o == 2) { searchByKeyword(finalMap, scanner); } else if (o == 3) { searchAll(finalMap); } } } scanner.close(); } public static void searchSingleField (Map<String, Map<String, String>> finalMap, Scanner scanner){ System.out.println("Name of the company"); String companyName = scanner.nextLine(); Map<String, String> card = finalMap.get(companyName); if (card == null) { System.out.println("Company not exist"); return; } System.out.println("What information would you like: (Name/Mail/Number/Address)"); String field = scanner.nextLine(); String value = card.get(field); System.out.println(value == null ? "Field not exist" : value); } public static void searchByKeyword (Map<String, Map<String, String>> finalMap, Scanner scanner){ System.out.println("What do you know:"); String keyword = scanner.nextLine(); int matchCount = 0; // 正确遍历外层Map的所有条目 for (Map.Entry<String, Map<String, String>> entry : finalMap.entrySet()) { String companyName = entry.getKey(); Map<String, String> card = entry.getValue(); // 匹配内层Map的所有字段 if (keyword.equals(card.get("Name")) || keyword.equals(card.get("Mail")) || keyword.equals(card.get("Address")) || keyword.equals(card.get("Number"))) { System.out.println("Company: " + companyName + ", Info: " + card); matchCount++; } } if(matchCount == 0){ System.out.println("It doesn't exist"); } } public static void searchAll (Map<String, Map<String, String>> finalMap){ for (Map.Entry<String, Map<String, String>> entry : finalMap.entrySet()) { System.out.println("Company: " + entry.getKey() + ", Info: " + entry.getValue()); } } }
内容的提问来源于stack exchange,提问作者Computerdude123
相关产品推荐
相关产品推荐

