我在Java HashMap上有一个奇怪且意外的行为,代码的一部分仅用于测试。
要在将对象存储到会话之前尝试为对象设置唯一ID,我会使用if{}else{}
语句,但我发现自己的应用中出现了错误。
生成ID用于测试目的,因为当前没有数据库实际存储数据,同时存储在会话中。
这是我的代码片段:
...
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()
的{{1}}为空
但测试未输入Map<Integer,Booking> bookings
声明
另一方面,在一个全新的会话中(在重新启动浏览器或退出并重新登录之后),测试确实按预期输入了if语句。
经过测试,我改变了if
的条件
至(bookings==null)
进一步的测试表明,在新会议上注册预订时仅使用(bookings==null || bookings.isEmpty())
会导致NPE。
所以我想知道Map是否有可能是非null而没有值(显然,是的,但我也问自己是怎么回事)以及它之后怎么没有返回null被完全清空?
虽然我在(bookings.isEmpty()
语句之后得到它是空的,但在new
调用之后它是怎么回事?这似乎很明显,因为会话中还没有存储Map,但同时由于没有session.getAttribute()
语句,它似乎很奇怪。
答案 0 :(得分:1)
如果
if (bookings == null)
是真的,而不是你没有地图(与空地图不同)。
如果执行else
块,则表示引用了地图。你对地图中的元素数量一无所知。你可能想要这样的东西:
if (bookings == null)
{
bookings= new HashMap<Integer, Booking>();
identificator = 1;
} else if (bookings.isEmpty())
{
identificator = 1;
}
else
{
identificator = Collections.max(bookings.keySet()) + 1;
}
回答这个问题:
它完全清空后怎么没有返回null?
看看这段代码:
Map<Integer, Booking> map = new HashMap<>();
我从未在地图中输入任何键/值对,因此它是空的。这就是我将一些键/值对放入其中的状态,然后再将其删除。 map
为空,但没有理由null
。null
。如果是{{1}}我们将来再也无法添加任何内容。
答案 1 :(得分:1)
HashMap
可以是null
(如果没有初始化)或为空(如果已初始化但未输入任何对象)。
从地图中删除对象会将其返回“空”状态(并且不 null
)。
new
语句为对象分配内存,并将其创建为空HashMap
(和不 null)
答案 2 :(得分:1)
null 并且为空是完全不同的概念。当变量(引用类型)为null时,它指向无处。你根本没有HashMap
。你只有一个空的指针(不是空的HashMap
)。您可以使用HashMap
创建新的bookings = new HashMap<Integer, Booking>()
。之后,你有空 HashMap
。你实际上有一个HashMap
,但里面什么都没有。
同样,当您从HashMap
中删除所有元素时,它将变为为空,而不是 null 。要使它null
,你必须明确地这样做:
bookings = null;