テスト専用のコードの一部で、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
マップに予約が 1 つしか含まれていないときに、マップ内の予約を削除すると、エラーが発生しました。その後、もう 1 つ登録しようとすると、次のエラー原因とステートメント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 が値のない非 null になる可能性があるかどうか疑問に思っていました (明らかに、そうですが、どうすればよいか自問しています)、完全に空になった後に null に戻らなかったのはなぜですか?
new
そして、ステートメントの後にそれがnullであることがわかりましたが、なぜそれがsession.getAttribute()
呼び出しの後に来るのでしょうか? セッションにまだ Map が保存されていないので明らかですが、同時にnew
ステートメントがなかったので奇妙に思えます。