2013-02-27 45 views
0

我对Java HashMap有一些奇怪的和意想不到的行为,仅仅用于测试的一部分代码。我可以有一个非空的hashmap,其中没有任何键吗?

要尽量将其存储在会议上,我使用if{}else{}声明,但我发现自己与我的应用程序错误之前一个唯一的ID设置为一个对象。为测试目的,产生

的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;

所以:

  1. arrayKeys.length -1 == -1 // true
  2. 这意味着arrayKeys.length == 0 // true
  3. 这又意味着从Map<Integer,Booking> bookings所述keySet()是空

  4. 但测试没有进入if声明

在另一方面,在一个全新的会话(或重新启动浏览器或重新登录并在后),测试没有进入if语句作为预期。

经过测试,我将自己的状况从(bookings==null)
改为(bookings==null || bookings.isEmpty())
进一步的测试表明,只使用(bookings.isEmpty()在新会话中注册预订时导致NPE。

所以我想知道是否有可能一个地图是非空的没有任何价值(显然,是的,但我也问自己是如何)以及它怎么没有返回后为null它完全被清空了?

尽管我得到它在new声明后为空,怎么会在session.getAttribute()调用之后呢?这似乎很明显,因为没有地图存储在会话中,但同时它似乎很奇怪,因为没有new声明。

回答

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; 
} 

要回答这个问题:

怎么就没有回零后,这是完全清空?

看看这段代码:

Map<Integer, Booking> map = new HashMap<>(); 

我从来没有进入任何键/值对进入地图,所以它是空的。这与我将一些键/值对放入其中的状态相同,然后再将其删除。 map为空,但没有理由为null。如果它是null我们未来不能再添加任何东西。

1

A HashMap可以是null(如果未初始化)或空(如果初始化但没有输入对象)。 从地图中删除对象将其返回到“空”状态(并且而不是null)。

new声明分配内存的对象,并创建为空HashMap(和空)

1

作为并且是是完全不同的概念。当变量(引用类型)为空时,它指向无处。你根本没有HashMap。你只需要一个空的指针(不是空的HashMap)。您使用bookings = new HashMap<Integer, Booking>()创建新的HashMap。之后,你有一个HashMap。你有一个HashMap,但它里面没有任何东西。

此外,当您从HashMap删除所有的元素,它成为,不。要做到这一点null,你必须明确这样做:

bookings = null; 
相关问题