Hashmap giving NullPointerException

Discussion in 'Spigot Plugin Development' started by Invaerne, May 30, 2017.

  1. Hi guys,

    I'm doing a little plugin that will count the caught fishes and store this information in a hashmap.
    The information from the hashmap is then displayed on a scoreboard - which works perfectly fine, but I do get an odd error, refering to this line:

    Code (Text):
    fish.put(p.getName(), fish.get(p.getName()) +1);

    Any ideas?

    Code (Text):
    Caused by: java.lang.NullPointerException
            at me.korupensel.rataniel.pociag.ListenerClass.onPlayerInteract(ListenerCla
    ss.java:134) ~[?:?]
            at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source) ~[?:?]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1
    .8.0_121]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_121]
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:302) ~[spigot.jar:git-Spigot-a3f6ea5-a2af8f0]
            ... 18 more

    Code (Text):
         

    public class ListenerClass implements Listener
    {
         FishPoint fishPlugin;
         private HashMap<String, Boolean> caughtFish;
         private HashMap<String, Boolean> registered;
         private Scoreboard board;    
         public HashMap<String, Integer> fish;
         
         public ListenerClass(FishPoint plugin)
         {
           plugin.getServer().getPluginManager().registerEvents(this, plugin);
           this.fishPlugin = plugin;
           caughtFish = new HashMap<String, Boolean>();
           registered = new HashMap<String, Boolean>();
           fish = new HashMap<String, Integer>();
         }



    @EventHandler
          public void onFish(PlayerFishEvent e)
          {        
                boolean EventEnabled = this.fishPlugin.getConfig().getBoolean("EventEnabled");
           
                Player p = e.getPlayer();
               
                    if (EventEnabled) {
             
                        if (e.getState().equals(State.FISHING)){
                            if (registered.get(p.getName()) != null ) {
                                if (!(registered.get(p.getName()))){
                                    String name = e.getPlayer().getName();
                                    fish.put(p.getName(), 0);
                                    registered.put(p.getName(), true);
                                }
                               
                            } else {
                               
                            }
               
                           
                            p.sendMessage("test3");
                        }

                        p.sendMessage("test");
             

             
                        if (e.getState().equals(State.CAUGHT_FISH)) {
                            String name = e.getPlayer().getName();
                            fish.put(p.getName(), fish.get(p.getName()) +1);
                            caughtFish.put(p.getName(), true);
                            p.sendMessage("heh");
                            scoreboard(p);
                            refresh(p);

       

                        }
                 
                }
         
          }
         
    /SPOILER]
     
  2. I don't know what's on line 134 but try creating an int and adding that int to the hashmap instead.
     
  3. ScarabCoder

    ScarabCoder Retired Resource Staff
    Retired

    Nullpointer means that the entry you're trying to get doesn't exist.
    In this case, when you use fish.get(p.getName), it can't find an entry with that key. If you want it to always start at 0, you could listen to the PalyerJoinEvent and set it there.

    Also, using the player's name isn't a good idea (even if it's temporary, it's not really proper). Use p.getUniqueID() instead.
     
  4. Just a note, don't use HashMap to store something mapping to a Boolean value, use List#contains
    Also, make null checks before then. Check if they are in the map before you try to get them from the map.


    Sent from my iPhone using Tapatalk
     
  5. Choco

    Moderator

    You did not give us the code that is generating the error. That method has nothing to do with your exception... The error is being thrown from a method titled "onPlayerInteract". You gave us a "onFish()" method.
     
  6. Oh, nice spot.


    Sent from my iPhone using Tapatalk
     
  7. Also if you're going to use a collection solely for checking if its contained, use a Set, its faster.
     
    • Agree Agree x 1
  8. There is no "onPlayerInteract"...
     
  9. Check at:
    me.korupensel.rataniel.pociag.ListenerClass

    In there should be an onPlayerInteract method

    Which means that you didn't show us your whole ListenerClass when you tried to show us the error. Either that or the stack trace is outdated and you should post the current stacktrace.


    Sent from my iPhone using Tapatalk
     
  10. Good point.

    Code (Text):
    Caused by: java.lang.NullPointerException
            at me.korupensel.rataniel.fish.ListenerClass.onFish(ListenerClass.java:73) ~[?:?]
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0
    _121]
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0
    _121]
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1
    .8.0_121]
            at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_121]
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.ja
    va:302) ~[spigot.jar:git-Spigot-a3f6ea5-a2af8f0]
            ... 19 more
    >
    >

    Code (Text):
          @EventHandler
          public void onFish(PlayerFishEvent e)
          {        
                boolean EventEnabled = this.fishPlugin.getConfig().getBoolean("EventEnabled");
         
                Player p = e.getPlayer();
             
                    if (EventEnabled) {
           
                        if (e.getState().equals(State.FISHING)){
                            if (registered.get(p.getName()) != null ) {
                                if (!(registered.get(p.getName()))){
                                    String name = e.getPlayer().getName();
                                    fish.put(p.getName(), 0);
                                    registered.put(p.getName(), true);
                                }
                             
                            } else {
                             
                            }
             
                         
                            p.sendMessage("test3");
                        }

                        p.sendMessage("test");
           

           
                        if (e.getState().equals(State.CAUGHT_FISH)) {
                            String name = e.getPlayer().getName();
    ////73///////////////////////////////////////////////////////////////
                            fish.put(p.getName(), fish.get(p.getName()) +1);
    ////74///////////////////////////////////////////////////////////////
                            caughtFish.put(p.getName(), true);
                            p.sendMessage("heh");
                            scoreboard(p);
                            refresh(p);

     

                        }
               
                }
       
          }
     
  11. And what line is erroring out now?
    Edit just saw


    Sent from my iPhone using Tapatalk
     
  12. You are getting the error because the player isn't in the map yet.


    Sent from my iPhone using Tapatalk
     
  13. I think getOrDefault will do the job. Use fish.put(p.getname(), fish.getOrDefault(p.getname (), 0) + 1);
    Sorry if I've got errors in my code, I'm on my phone so no IDE is checking this.
     
    • Agree Agree x 1
  14. Choco

    Moderator

    Even better, Map#compute() to replace the whole statement
    Code (Java):
    fish.compute(p.getName(), (k, v) -> v == null ? 1 : v++);
    That will put a new value in the map if it's mapped to null or if the mapping does not yet have a key/value. If it does, it will just increment its value by 1. This is ignoring all the other mistakes regarding this code, but the above statement works perfectly fine in the current situation
     
    #14 Choco, May 30, 2017
    Last edited: May 30, 2017
    • Like Like x 1
  15. instead of using a hashmap with string boolean as key and value, just use a set implementation and check whether or not the set contains the player name or uuid.

    Code (Java):

    private Set<String> caughtFish = new HashSet<>();

    public boolean hasCaughtFish(Player player) {
         return this.caughtFish.contains(player.getName());
    }
    also, maybe some methods to actually increment / manage the amount value in the hashmap, instead of constantly repeating Map#put
     
  16. Just to one up you, use Map::merge(K, V, Function<V, V>). It'll insert the value if the key is unknown, or call the function with the old and new value if known. It'll save you a null check (you can just call map.merge(k, 1, Integer::sum) ;) )
     
    • Like Like x 1
  17. Code (Text):
    fish.put(p.getName(), (fish.get(p.getName()) != null) ? (fish.get(p.getName()) + 1) : 1);
     
  18. Choco

    Moderator

    -bows down-
    I will accept defeat
     
  19. No... Stop... Don't....
     
  20. IDK made that up in 2 secs but took me 2 mins to write out