我在用常量值实例化常规HashMap时遇到问题。我打算在租车服务中跟踪各种汽车的库存;以汽车类型为键,以num值作为租金。 我尝试使用createAvailable cars方法,该方法将地图初始化为每种车型的最大数量的常量。为了进行进一步的测试,我还包含了setMaxCarsAvailable方法。尽管如此,我还是从canReserveVehicle方法enter image description here的行中得到了NullPointer异常,该异常指定如果有0辆可用的汽车,那么您将无法预订车辆。如何正确使用汽车地图处理库存?我应该放在哪里?我尝试使用静态方法,后来将其包含在没有运气的构造函数中。参见下面的代码。(我提供了堆栈跟踪的图片,其中显示了testCase类中的错误。希望所有这些额外的信息对您有帮助)
MongoClient.connect()
}
带有“ java.lang.NullPointerException” CarReservationController.canReserveCarVehicle的测试用例看起来像这样
public class CarReservationController {
String phoneNumber;
long numDays = 0;
Vehicle vehicle;
VehicleType vType;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public static final int MAX_ECONOMY = 10; //used this to track the amount of cars available to rent. This was applied in the canReserveVehicle and addReservation methods
public static final int MAX_PREMIUM = 10;
public static final int MAX_SUV = 5;
public CarReservationController()
{
availableCars = createAvailableCarsMap(); //this is my attempt at instantiating my availableCars map to contain (VehicleType.ECONOMY, 10), (VehicleType.PREMIUM, 10), map.put(VehicleType.SUV, 5); ;
}
Map<VehicleType, Integer> availableCars;
Map<VehicleType, PriorityQueue<Date>> reservedVehicleReturnDates = new HashMap<>(); // Map from vehicle type to reserved car end dates. This will hold all the current reservations end dates for each vehicle type
//was public static map
public HashMap<String, List<CarReservation>> reservationsMap = new HashMap<>();
//previously private static Map...
private Map<VehicleType, Integer> createAvailableCarsMap() {
Map<VehicleType, Integer> map = new EnumMap<VehicleType, Integer>(VehicleType.class);
map.put(VehicleType.ECONOMY, MAX_ECONOMY);
map.put(VehicleType.PREMIUM, MAX_PREMIUM);
map.put(VehicleType.SUV, MAX_SUV);
return map;
}
public void setMaxCarsAvailable(VehicleType v, int maxAvailable) {
availableCars.put(v, maxAvailable);
}
//I UPDATE carReservationsMap here..this adds an actual reservation but first it checks the boolean canReserveVehicle below
public void addReservation(CarReservation res) throws Exception //right here
{
Date sDate = res.getStartDate(); //HERE
Date eDate = res.getEndDate(); //HERE
String phoneNumber = res.getPhoneNumber();
if(canReserveVehicle(vType, phoneNumber, sDate, eDate)) {
if (reservationsMap.containsKey(phoneNumber)) {
List<CarReservation> currCustomerRes = reservationsMap.get(phoneNumber);
currCustomerRes.add(res);
reservationsMap.put(phoneNumber, currCustomerRes);
} else {
List<CarReservation> currCustomerRes = new ArrayList<CarReservation>(Arrays.asList(res));
reservationsMap.put(phoneNumber, currCustomerRes);
}
int countForVehicleType = availableCars.get(vType);
availableCars.put(vType, countForVehicleType - 1);
if (reservedVehicleReturnDates.containsKey(vType)) {
reservedVehicleReturnDates.get(vType).add(eDate);
} else {
PriorityQueue<Date> q = new PriorityQueue<Date>();
reservedVehicleReturnDates.put(vType, q);
}
}
}
//NULL POINTER EXCEPTION COMING UP HERE FROM JUNIT TESTS
public boolean canReserveVehicle(VehicleType v, String phoneNumber, Date startDate, Date endDate) throws ParseException
{
PriorityQueue<Date> reservedVehicleQueue = reservedVehicleReturnDates.get(v);
if(endDate.before(startDate))
return false; // check that the start date of the reservation is before the end date
if (availableCars.get(v) == 0) { /// SAYS THERE IS A NULL POINTER EXCEPTION from here... because availableCars is still 0..
Date nextCarReturnDate = reservedVehicleQueue.peek();
if(nextCarReturnDate.after(startDate))
return false; // return false if a reserved car is not going to be available before the new customer is requesting one.
}
else {
// If a car that will become available before the customer requests it, remove it from the queue and replace with the
//requesting customer's return date (as they now lay claim to the car)
reservedVehicleQueue.poll();
reservedVehicleQueue.add(endDate);
}
//these are comparing strings.
if (reservationsMap.containsKey(phoneNumber)) {
List<CarReservation> resByCustomer = reservationsMap.get(phoneNumber);
CarReservation lastResByCustomer = resByCustomer.get(resByCustomer.size() - 1);
Date lastResEndDate = sdf.parse(lastResByCustomer.endDate);
if (startDate.before(lastResEndDate)) { //1 customer can only have one rental at a time within the system.
return false;
}
}
return true;
}
答案 0 :(得分:0)
有几个问题使调试变得很复杂。
对于您所问的问题而言,也许最重要的一点是,它没有完整的堆栈跟踪信息,但是您看到的NPE是来自availbleCars.get(v)
还是来自availableCars.get(v) == 0
,这并不是很明显。
由于不知道ReservationSystem::addReservation
方法的作用,因此我认为不可能排除任何一种可能性。
可能性1
但是,如果问题来自availableCars.get(v) == 0
,则可能是您选择使用Integer
而不是==
比较.equals()
和数字基元之间的相等性。请参阅前面的答案,以获取更完整的讨论:Why comparing Integer with int can throw NullPointerException in Java?
可能性2
如果问题来自availableCars.get(v)
(availableCars
本身是null
),那么您可能无法确定如何实例化availableCars
映射。在那里使用的方法不必是静态的,也不需要创建的设置器。
后续步骤
要解决此问题,建议您使用断点或使用调试语句将该比较分为两个步骤-首先检查availableCars
是否为空,然后检查availableCars.get(v)
是否为Integer
,然后使用.equals()
检查与0
的相等性。
此外,您可以尝试对方法进行单元测试,以分别实例化availableCars
映射和ReservationSystem::addReservation
方法,以帮助缩小可能出现的错误的范围。