Solved Is using a static hashmap in a constructor class bad?

Discussion in 'Spigot Plugin Development' started by PracticalX, Feb 13, 2019.

  1. Lets say I have a class to create.. a monster for example, would it be bad to save that monster in a static hashmap? If I didn't save it in a hashmap how could I get the monster's instance that's within my monster class?

    Here's the example in code,

    Code (Text):

    public class Mob {
       
        public static HashMap<UUID, Mob> mobs = new HashMap<UUID, Mob>(); // The hashmap we'd be saving the mob in to
       
        Entity entity; // Our entity that is generated
       
        Mob(Location location) { // Constructor
            this.entity = location.getWorld().spawnEntity(location, EntityType.ZOMBIE); // Making our entity
        }
    }
     
    Would it be a bad idea to do something along the lines of this,

    Code (Text):

    mobs.put(entity.getUniqueId(), this);
     
    If it is a bad idea then how should I do this properly? Thanks!
     
  2. Usually it depends on implementation on if you should use static. Without further knowledge of what you're trying to with this code ie) why you need to track it's UUID, I can't give much advice. Static is a wonderful thing if you know how to use it properly. Unless you have a good reason to, your hashmap should not be public. That gets into the idea of encapsulation meaning making data available outside of that single class's internal workings only if it needs to be. (Hope I explained that well) I believe you should look at making a MobManager class to store and manage that data there.
     
    • Agree Agree x 1
  3. I would advise against using static generally speaking. This StackOverflow question might prove helpful.
    To get the monster instance you could create a method in your Mob class:
    Code (Java):
    public Mob getMob(UUID uuid)
    {
        return mobs.get(uuid); //Note that this can return null
    }
    The object that needs to get the Mob, should have the instance of Mob that contains the list. This can simply be achieved by having following parameter in its constructor: Mob mob. You'd also need a 'private Mob' field in that class, which would hold the respective value of the constructor.
     
    • Like Like x 2
  4. It would be wiser to create a MobManager class. You'd then add the map there as private and final, along with a public getter. Then, you'd access that class from your main class using dependency injection. (You'd have to initiate the MobManager class only once)
     
    • Like Like x 1
  5. The mobs (class) will need to be accessible from many other classes, such as Event classes, which I believe are static.

    @Shin1gamiX I've created a MobManager class now, which has my hashmap but nothing else, as this is where I get confused. Here's an example of when I'll be creating a mob.. A user loads in a chunk, if that chunk is a "mob" chunk then we'll spawn a mob there.

    Here's an example of when I'll need to retrieve that mob.. A user punches it, then I need to get that mob's instance.
     
  6. When spawning the mob, simply put the mob's uuid in the map along with a new instance of the Mob class covering all your needs.
     
    • Informative Informative x 1
  7. That's what I attempted doing, but I can't figure out a way to retrieve that mob from the hashmap from a static environment.

    Code (Text):

    public class Mob {
        Entity entity; // Our entity that is generated
       
        public Mob(Location location) { // Constructor
            this.entity = location.getWorld().spawnEntity(location, EntityType.ZOMBIE); // Making our entity
            new MobManager(this);
        }
    }

     
    MobHandler

    Code (Text):

    public class MobManager {
       
        private final HashMap<UUID, Mob> mobs = new HashMap<UUID, Mob>(); // The hashmap we'd be saving the mob in to
       
        public Mob getMob(UUID uuid) {
            return mobs.get(uuid);
        }
       
        public MobManager(Mob mob) {
            mobs.put(mob.entity.getUniqueId(), mob);
        }
    }
    [code]
     
  8. You can put your Map in your Mob class, that's a good way to go, you don't need another class.
    Static keyword can be used for something who is the same for all your instance and your Map need to be the same for all your instance and allow you to get your Mob easily using static getter

    But put your Map as private and create a getter for getting your mob instance in the map.

    Example using a basic User class:
    Code (Java):
    public class User
    {
        private static final Map<UUID, User> users = new HashMap<>();

        public static User getUser(Player player)
        {
            return users.get(player.getUniqueId());
        }

        private final Player player;
        private double currency = 0.0;

        public User(Player player)
        {
            this.player = player;
            users.put(player.getUniqueId(), this);
        }

        public Player getPlayer()
        {
            return player;
        }

        public double getCurrency()
        {
            return currency;
        }

        public void setCurrency(double currency)
        {
            this.currency = currency;
        }
    }
    You can use it where you want now using your static getter
    Code (Java):
    @EventHandler
    public void onPlayerDeath(PlayerDeathEvent e)
    {
        User user = User.getUser(e.getEntity());
        if (user != null)
        {
            user.setCurrency(0);
        }
    }
    Using static getter you can also make sure to return a non null value for removing the null check when calling User#getUser
    Code (Java):
    public static User getUser(Player player)
    {
        return users.getOrDefault(player.getUniqueId(), new User(player));
    }
     
    #8 FrozenLegend, Feb 13, 2019
    Last edited: Feb 13, 2019
    • Useful Useful x 1
  9. Oh! I wasn't aware that you could make a static reference to a non-static hashmap! That's wonderful. Read that wrong,

    So I should just keep the hashmap static then?
     
  10. Yeah keep it static but make sure to put it private and create a public getter for getting the value from the Map

    Btw just for information, you can access a static field in your instance method/constructor (instance method = non static method) but you can't access your instance field in a static method
     
  11. Thank you very much! I just wanted to make sure it wouldn't be frowned upon if I used a static hashmap in a constructor like this.
     

Share This Page