在仅用于测试的部分代码上,我在 java HashMap 上有一个奇怪和意外的行为。
为了在将对象存储在会话中之前尝试为其设置唯一 ID,我使用了一条if{}else{}
语句,但我发现自己的应用程序出现错误。
ID 是出于测试目的而生成的,因为目前没有数据库来实际存储数据,同时存储在 session 中。
这是我的代码片段:
...
HttpSession session = request.getSession();
Map<Integer, Booking> bookings = (HashMap<Integer, Booking>) session.getAttribute(SESSION_BOOKINGS);
// Generates ID
if (bookings == null)
{
bookings= new HashMap<Integer, Booking>();
identificator = 1;
}
else
{
Object[] arrayKeys = (Object[]) bookings.keySet().toArray();
Arrays.sort(arrayKeys);
identificator = (Integer) arrayKeys[arrayKeys.length - 1] + 1;
}
...
//... The rest is setting the ID to the current worked on booking,
//... putting the ID/booking pair in the bookings map
//... and storing the map in session, which worked fine
当地图只包含一个预订时,删除地图中的预订后出现错误。当我在那之后尝试再注册一个时,我收到了一个错误,错误原因如下java.lang.ArrayIndexOutOfBoundsException: -1
,并且跟踪链接到我的else
语句的最后一行:identificator = (Integer) arrayKeys[arrayKeys.length - 1] + 1;
所以:
arrayKeys.length -1 == -1 // true
- 意思就是
arrayKeys.length == 0 // true
这反过来意味着
keySet()
fromMap<Integer,Booking> bookings
是空的但是测试没有进入
if
语句
另一方面,在一个全新的会话上(在重新启动浏览器或注销并再次登录之后),测试确实按预期输入了 if 语句。
测试后,我将状态从 更改(bookings==null)
为(bookings==null || bookings.isEmpty())
。
进一步的测试表明,(bookings.isEmpty()
在新会话上注册预订时,仅使用导致 NPE。
所以我想知道一个 Map 是否有可能是 non-null 并且其中没有任何值(显然,是的,但我也在问自己如何)以及它为什么在完全清空后没有返回 null ?
尽管我在new
声明之后知道它是空的,但它在session.getAttribute()
调用之后是怎么来的?这似乎很明显,因为会话中还没有存储 Map,但同时由于没有new
声明,这看起来很奇怪。