NullPointerException podczas użycia ::containsKey na ConcurrentHashMap

0

Cześć. Zaczynam trochę szkrobać w Javie. Po raz pierwszy używam struktury danych ConcurrentHashMap. Tutaj mniej więcej mój kod:

        private Player target; // zostaje później zainicjalizowany, na pewno, sprawdzałem na każdy możliwy sposób
        private ConcurrentHashMap<Integer, Long> effects_ends = new ConcurrentHashMap<Integer, Long>();
        ...
        if(this.effects.isEmpty() || duration==0 || max_effects==0 || this.target==null) { //null check na this.target
            player.sendMessage("first check progress");
            this.remove();
            return;
        }
        int target_hash = this.target.hashCode();
        // tu był println ( dotąd wypisywało )
        if ((!affect_before_end) && (effects_ends.containsKey(target_hash))) {
            // tu był println
            if ((Instant.now().toEpochMilli() - effects_ends.get(target_hash) < this.duration * 20)) {
                 // tu był println
                this.remove();
                return;
            } else effects_ends.remove(target_hash);
        }
       // tu był println

Dostaję NPE w containsKey (wiem, bo robiłem mnóstwo println i wychodzi na to, że właśnie ten check wywala NPE), jednak nie mam zielonego pojęcia dlaczego. Null check jest.

2

Jak nie używasz to zacznij używać IntelliJ'a w wersji darmowej, uruchom w nim projekt. Postaw breakpointa na linijce od której zaczynasz analizować swój kod używaj klawisza F8 aby przechodzić linijka po linijce. W okienku debug będziesz miał wartości zmiennych aktualnie używanych w aplikacji. Oczywiście projekt w IDE uruchom w trybie debug, Ucząc się obsługi debuggera o wiele łatwiej znajdziesz błąd i jest to dużo lepsza metoda do ich szukania niż printline'y.

TL;DR: Użyj debuggera w IntelliJu.

0

Masz race condition w linijce 11 i 13.

1

Bardzo wątpię, żeby containsKey zwracał ci NPE.

affect_before_end - co to jest?

0
        int target_hash = this.target.hashCode();
        // tu był println ( dotąd wypisywało )
        if ((!affect_before_end) && (effects_ends.containsKey(target_hash))) {

Przepraszam ale WTF? Czemu liczysz hashCode ręcznie a potem w ogóle operujesz jakimiś intowymi hashami? Po to te struktury danych są generyczne, zebyś tak nie robił! Czemu to nie jest po prostu Map<Player,Long>?

Dalej nie rozumiem czemu operujesz jakmiś printami skoro Java pokaże ci stacktrace i powie dokładnie co i gdzie jest nullem. Pokaż taki przykładowy stracktrace.

0
Shalom napisał(a):
        int target_hash = this.target.hashCode();
        // tu był println ( dotąd wypisywało )
        if ((!affect_before_end) && (effects_ends.containsKey(target_hash))) {

Przepraszam ale WTF? Czemu liczysz hashCode ręcznie a potem w ogóle operujesz jakimiś intowymi hashami? Po to te struktury danych są generyczne, zebyś tak nie robił! Czemu to nie jest po prostu Map<Player,Long>?

Dalej nie rozumiem czemu operujesz jakmiś printami skoro Java pokaże ci stacktrace i powie dokładnie co i gdzie jest nullem. Pokaż taki przykładowy stracktrace.

Akurat Map<Player, Long> może być trochę niebezpieczne.
Bezpieczniejszą opcją jest użycie UUID jako klucza, które można pobrać za pomocą metody player.getUniqueId().

1 użytkowników online, w tym zalogowanych: 0, gości: 1