0

I have a situation where I have a User that is a certain profession, so I have something like:

public abstract class Job
{
    private static String name;
    public static String getJobName() { return name; }
}

and

public class Baker extends Job
{
    // I realize this is probably wrong, but not the main point
    Baker() { name = "Baker"; }
}

Then i wanted to store the User->Profession in a map like

Map<User, Class<? extends Job>> uJobs = HashMap<User, Class<? extends Job>>();
uJobs.put(user, Baker.class); // This seems to work
String jobName = uJobs.get(user).getJobName(); // This not so much, and the IDE (eclipse) just somes 'class' specific stuff, not Job specific stuff.

Any advice is appreciated. The core goal here is to map 1 Object to a Class that I can just call static methods from without needing an instance for every Object.

John
  • 590
  • 4
  • 13

4 Answers4

2

Don't put the class object in the hash map, just put an instance of the class.

Map<User,Job> uJobs=new HashMap<User, Job>();
uJobs.put(user, new Baker());
String jobname=uJobs.get(user).getJobName();

Better still, you probably don't need to create a new instance of Baker each time you add a user. Make a static or a singleton.

class Baker extends Job
{
  public static Job instance=new Baker();
  public String getJobName()
  {
    return "Baker";
  }
}
...
uJobs.put(user, Baker.instance);

If the only thing that distinguishes the jobs is data, you don't need to subclass. You could instead say

class Job
{
  public static Job BAKER=new Job("baker", 7);
  public static Job BUTCHER=new Job("butcher", 12);
  public static Job CANDLESTICK_MAKER=new Job("candlestick maker", 27);

  private String name;
  private int whateverCode;

  pubilc Job(String name, int whateverCode)
  {
    this.name=name;
    this.whateverCode=whateverCode;
  }
  public String getJobName()
  {
    return name;
  }
  public int getWhateverCode()
  {
    return whateverCode;
  }
}
...
uJob.put(user, Job.BAKER);
Jay
  • 26,876
  • 10
  • 61
  • 112
2

If the set of jobs is predefined (which seems to be the case because you want to create one class for each), the Java way would be to put the jobs in an enum - so there is only one BAKER object in your application, without resorting to the Singleton Pattern, which would clearly be a bad design in your case:

public enum Job {
    BAKER("Baker"),
    TEACHER("Teacher");

    private final String name;
    private Job(String name) {this.name = name;}

    public String getName() {return name;}
}

Then you can use a Map:

Map<User, Job> uJobs = new HashMap<User, Job>();
uJobs.put(user, Job.BAKER); // This seems to work
String jobName = uJobs.get(user).getName();
Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
0

You can use a Singleton Patern

An other point, when you call uJobs.get(user).getJobName(), your variable name is not equal to 'Baker', because any Baker instance has been called.

Jérôme Boé
  • 2,752
  • 4
  • 21
  • 32
  • Using a singleton in this case seems very inappropriate. – assylias Aug 02 '12 at 18:32
  • _The core goal here is to map 1 Object to a Class that I can just call static methods from without needing an instance for every Object._ I didn't find Singleton inappropriate, but if you say so ... – Jérôme Boé Aug 02 '12 at 18:39
  • I'm not saying that it does not answer that question, I'm saying that using a singleton to manage the Jobs of Users seems a bad idea. – assylias Aug 02 '12 at 19:18
  • Yes I totaly agree. I should have just comment the question ;) – Jérôme Boé Aug 02 '12 at 19:22
0

It sounds like you want to implement a Singleton. I wouldn't recommend using static variables in this case. What you want is a Singleton cache of all the objects.

public class JobCache {
  private Map<User, ? extends Job> internalCache;

  private static final JobCache instance;

  private JobCache() {}

  public static JobCache getInstance() {
      if (instance == null)
        instance = new JobCache();
      return instance;
  }

  public void putJob(User u, Job j) {
      internalCache.put(u, j);
  }

  public Job getJob(User u) {
      return internalCache.get(u);
  }
}

Nowadays Singletons are frowned upon. This is because it's harder to test them, since you can't create instances of them and pass them around. But this is an advanced topic. For now, a singleton should solve your problem.

Community
  • 1
  • 1
Jose
  • 1,616
  • 4
  • 26
  • 38