调用其他类Getter获取ArrayList元素失败,报空指针异常求助
我来帮你拆解代码里的核心问题,这两个点就是导致你遇到异常、判断逻辑不执行的根源:
1. 字符串比较用==而非equals(),导致匹配失败
你在getPrice方法里的判断逻辑用了==比较字符串:
if(shoppingList.get(i).getItemName() == itemName)
在Java里,==比较的是对象的内存引用地址,而不是字符串的实际内容。哪怕两个字符串内容完全一样,只要不是同一个对象实例,==就会返回false。
另外,你的ShopItems构造函数里把传入的itemName转成了全大写:
itemName = i.toUpperCase();
但你查询时传的是"Pens"(首字母大写),存储的却是"PENS"(全大写),这也会直接导致匹配不上。
修复方案:
改用equals()比较内容,同时统一大小写避免匹配偏差:
// 把查询的名称也转成大写,和存储的格式统一 if(shoppingList.get(i).getItemName().equals(itemName.toUpperCase()))
如果担心传入的itemName为null引发空指针,可以反过来写更安全:
if(itemName.toUpperCase().equals(shoppingList.get(i).getItemName()))
2. 空指针异常的几个潜在来源
(1)ShopItems的setPrice方法参数缺失类型
你的setPrice方法有语法错误,参数p没声明类型:
private void setPrice(p){ price = Math.abs(p); }
必须补全参数类型,否则编译都通不过,间接引发运行时异常:
private void setPrice(double p){ price = Math.abs(p); }
(2)ShopLedger构造函数的冗余代码
你写的构造函数里,new ArrayList<>(s)已经把原列表的元素拷贝到shoppingList里了,后面的循环完全是多余的——相当于把刚拷贝的元素又重新赋值一遍,没有任何意义。如果原列表s里存在null元素,shoppingList里也会有null,遍历调用getItemName()时就会抛出空指针。
另外你注释里提到要做深拷贝,当前的浅拷贝只是拷贝了对象引用,修改原列表的元素会影响shoppingList。如果需要真正的深拷贝,应该创建新的ShopItems对象:
public ShopLedger(ArrayList<ShopItems> s){ shoppingList = new ArrayList<>(); for(ShopItems item : s){ // 跳过null元素,避免后续遍历空指针 if(item != null){ shoppingList.add(new ShopItems(item.getItemName(), item.getPrice())); } } }
(3)客户端初始化的潜在问题
确保你客户端初始化shoppingList时,每个元素都是有效的ShopItems对象,没有null。比如正确的初始化方式:
ArrayList<ShopItems> items = new ArrayList<>(); items.add(new ShopItems("Candy", 2.3)); items.add(new ShopItems("Book", 20.0)); items.add(new ShopItems("Pens", 5.5)); items.add(new ShopItems("Tape", 10.2)); ShopLedger ledger = new ShopLedger(items);
最终修复后的关键代码
修改后的ShopItems类
public class ShopItems { private String itemName; private double price; public double getPrice(){ return price; } public String getItemName(){ return itemName; } // 补全参数类型 private void setPrice(double p){ price = Math.abs(p); } public ShopItems(String i, double p){ itemName = i.toUpperCase(); setPrice(p); } }
修改后的ShopLedger类
import java.util.ArrayList; public class ShopLedger { private ArrayList<ShopItems> shoppingList; // 实现深拷贝+避免null元素 public ShopLedger(ArrayList<ShopItems> s){ shoppingList = new ArrayList<>(); for(ShopItems item : s){ if(item != null){ shoppingList.add(new ShopItems(item.getItemName(), item.getPrice())); } } } public Double getPrice(String itemName) { // 提前处理null参数 if(itemName == null){ return null; } String targetName = itemName.toUpperCase(); for(ShopItems item : shoppingList){ // 避免item为null引发空指针 if(item != null && targetName.equals(item.getItemName())){ return item.getPrice(); } } return null; } }
这样修改后,查询"Pens"时会自动转成"PENS"和存储的名称匹配,同时彻底避免了空指针异常,也实现了你想要的深拷贝效果。
内容的提问来源于stack exchange,提问作者lettuce

