Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Hashmap Value is a class, how do I call a method contained in the class that is the hashmap value?  RSS feed

 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a class with a hashmap. Loaded into the hashmap values are classes and the instance parameters for the class.
The code is selecting a random number between 1 and 4 and displaying the information for that row in the hashmap.
Each pet has different attributes.

Below is how I am loading the hashmap. Each of the objects has a petDescription method that is inherited from superclass animal and that method will output the instance variables.
The main method receives a value between "1" and "4" that is the key for the hashmap. The main needs to call the petDescription method so the instance variables are displayed.

How do I call the petDescription method of the class that is the value in the hashmap row for the key passed into main()?




 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First, your classes should be PetDog, PetCat, etc. It is convention in Java to start class names with an uppercase letter.

As for your question, assuming all those PetXxx classes implement a Pet interface or extend a Pet class, and inherit the petDescription method from there, then the best and easiest way to do what you want would be to use the generic type properly in the map:


Then, when you get an object out of the map, you and the compiler both know it's a Pet.


If you don't do that, you'll have to cast:

If your PetXxx classes don't inherit petDescription() from a common base type, then you have a design flaw.

Finally, I'll just point out that using a Map when your keys are all just sequential numbers kind of defeats the purpose. An array or List would be more suitable.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I will correct the class names, thank you for catching me on that.

The superclass is abstract and, yes, it does contain the petDescription method.

You are saying that it's okay to define the hashmap with the abstract superclass even though the subclasses have extended it and added their own constructors. That is what I did not understand before about inheritance.

Thank you for clearing up my puzzlement!

 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:You are saying that it's okay to define the hashmap with the abstract superclass even though the subclasses have extended it and added their own constructors.


Yup, exactly. And constructors have nothing to do with it.

When we do Map<String, Pet>, that just says that every value in the Map must be a Pet. Since anything that extends Pet IS-A Pet, using PetDog, etc. is allowed.

This is a very common way to use the Collections Framework.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
BUT there is still a problem . . . .




I do not want a new instance of Pet in the main method I want to call the petDescription method of the instance that was created in the hashmap because the petDescription needs to display the constructors that where loaded into that instance.

I have two dogs in the hashmap , if the hashmap key is "4" the "mutt " information needs to show , but if the hashmap key is "1" the beagle information needs to show. If I create Pet p I have a PetDog but the constructors are blank.
 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66304
152
IntelliJ IDE Java jQuery Mac Mac OS X
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What leads you to believe that:will create a new instance?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:the petDescription needs to display the constructors that where loaded into that instance.


You seem to misunderstand what "constructor" means. A constructor isn't something we display or load. A constructor is a block of code that executes to put a newly created object into a valid initial state.


I have two dogs in the hashmap , if the hashmap key is "4" the "mutt " information needs to show , but if the hashmap key is "1" the beagle information needs to show. If I create Pet p I have a PetDog but the constructors are blank.


"Constructors are blank" has no relevance here. If you do Pet p = netPet.get("4"), then you'll get back exactly the object that you put into the map witn put("4", whatever).
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Bear,

What leads you to believe that:
Pet p = newPet.get("1");
will create a new instance?


My confusion about this topic.


You are saying it is not a new instance but a pointer to the instance from the hashmap....

If it does not create a new instance where do the constructors go?

What prints out are the titles from the PetDog.petDescription(), such as "Breed: " but :beagle" doesn't print. I do not have any compiler errors. Maybe the issue is something in my subclasses ?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:
If it does not create a new instance where do the constructors go?


Ah ha! Now we see the heart of the problem!

When we call someMethod(new SomeObject()), we're not passing a constructor into that method. We're creating an object and passing a reference to that newly created object into the method.



And Map's put() method is no different. It's nothing special. It's just another method call.

 
Bear Bibeault
Author and ninkuma
Marshal
Posts: 66304
152
IntelliJ IDE Java jQuery Mac Mac OS X
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:You are saying it is not a new instance but a pointer to the instance from the hashmap....

Yes. As the method name implies, it is getting the instance from the map. Why would a new instance need to be created?

If it does not create a new instance where do the constructors go?

What constructors? Why would a constructor need to be involved? The instance was created via constructor when it was put into the map. Why would constructors be involved when getting the instance from the map?

What prints out are the titles from the PetDog.petDescription(), such as "Breed: " but :beagle" doesn't print. I do not have any compiler errors. Maybe the issue is something in my subclasses ?

How are you "printing"?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:
What prints out are the titles from the PetDog.petDescription(), such as "Breed: " but :beagle" doesn't print.


Then either petDescription() has a bug in it, or else you are calling petDescription() when you should be doing something else. Impossible to say without seeing what that method does, what it's intended to do, and what you're actually trying to accomplish.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator



Okay , so here is my understanding, that is probably wrong. When I load the hashmap with new PetDog I am passing parameters.


The parameters will be stored in the PetDog class by the PetDog constructor?

Then the petDescription method can use them since they are common to the class?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:
Okay , so here is my understanding, that is probably wrong. When I load the hashmap with new PetDog I am passing parameters.


The parameters will be stored in the PetDog class by the PetDog constructor?


You have two different things going on there:

1. You are creating a new instance of PetDog, and passing parameters to the constructor that's called as part of that creation step.

2. You are put()ing a reference to that newly created PetDog object into the map.

As I already stated, it's just like if you had done





Then the petDescription method can use them since they are common to the class?


Yes, but this has nothing to do with the Map. When you do Pet p = map.get(...), it doesn't matter that there's a map.get(...) call. All that matters is that p is declared to point to a Pet object, so we can use p to call any public method defined on Pet.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is my main class on FindPet. I understand that using the code below the p.petDescription should call petDescription because p. points to the object in the hashmap value.






1. You are creating a new instance of PetDog, and passing parameters to the constructor that's called as part of that creation step.


Yes, and that is the intention.



Correct, I understand that.

When you do Pet p = map.get(...), it doesn't matter that there's a map.get(...) call. All that matters is that p is declared to point to a Pet object, so we can use p to call any public method defined on Pet.


In the code at the beginning of this post I use your example from previous posts but the data isn't in the output. I know that the object exists because if a number is received by main() that isn't a key in the hashmap the program crashes.
This is my output



So what am doing that I should not be doing ? What are you writing that I am not understanding ?






 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:In the code at the beginning of this post I use your example from previous posts


Please copy/paste the exact code, or an SSCCE that demonstrates the problem, with no extra, unrelated code. Just describing the code is not helpful.

but the data isn't in the output. I know that the object exists because if a number is received by main() that isn't a key in the hashmap the program crashes.


As I already suggested, it sounds like there's something wrong with your petDescription() method, since that's the method that you're calling to get the String you're printing out, and that String is not what you expected it to be.

However, since you haven't shown us that method, it's impossible to say.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The PetDog class with the petDescription method is posted in full about 4 posts above this one. Thank you.
 
Tony Docherty
Bartender
Posts: 3271
82
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The problem is in the constructor.
You have used the exact same variable names for the instance variables and the constructor parameters (IMHO a bad idea, especially for beginners) but when assigning the parameters to the instance variables you haven't used "this." to specify you want the instance variable and so you are assigning each parameter back to itself, hence none of the instance variables are ever given values.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tony Docherty wrote:The problem is in the constructor.
You have used the exact same variable names for the instance variables and the constructor parameters.


Well spotted. I didn't notice that code posting.

@Margaret: Sorry, I somehow missed that post.

In case you're not clear on what Tony is saying, forget about constructors and maps and whatnot. Suppose you just have this:


What exactly do you think that will do?
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

You have used the exact same variable names for the instance variables and the constructor parameters (IMHO a bad idea, especially for beginners) but when assigning the parameters to the instance variables you haven't used "this." to specify you want the instance variable and so you are assigning each parameter back to itself, hence none of the instance variables are ever given values.


I figured it must be something like that because the object was being created and called. I will revise the variable names now.

Thank you!


My output now:




Many thanks to EVERYONE who helped me on this thread today. I have been banging my head on this problem for quite a while

I feel I have a much better understanding of hashmaps and constructors.

and I will sleep better tonight...

Cheers
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

better left unread...
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:

You have used the exact same variable names for the instance variables and the constructor parameters (IMHO a bad idea, especially for beginners) but when assigning the parameters to the instance variables you haven't used "this." to specify you want the instance variable and so you are assigning each parameter back to itself, hence none of the instance variables are ever given values.


I figured it must be something like that because the object was being created and called. I will revise the variable names now.

Thank you!


Glad you got it worked out.

Note that it's quite common, and perfectly acceptable, to use parameter names that match member variable names, at least in constructors and setter methods. You just have to know to do this.x = x; in order to distinguish the member x (this.x) from the local x (plain old "x").
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:Hi Jeff,

In case you're not clear on what Tony is saying, forget about constructors and maps and whatnot. Suppose you just have this:
x = x;
What exactly do you think that will do?


One x gets the value of the other x but it depends on what type of variable x is.


Yes, but since they're both just "x" (there is no "one x" vs. "the otther x"), it just copies the value that that x already has back into itself.

In other words, it does nothing at all.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Besides constructors and parameters are there any other kinds of values / objects that can have the same name and both have independent existences ?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
margaret gillon wrote:Besides constructors and parameters are there any other kinds of values / objects that can have the same name and both have independent existences ?


Can you show me an example of where you think a constructor has the same name as something else? Or what you think a constructor is? (Constructors can have the same names as other constructors, but the way you're using the word, it sounds like you don't have the right understanding in mind.)

A local variable (of which method parameters are a subset) can have the same name as a member variable. A member variable in a child class can have the same name as a member variable in a parent class, but this is a really bad idea.

A method can have the same name as another method, and often does (overriding and overloading).

Pretty much anything can have the same name as anything else, but there are only certain circumstances where it makes sense. I'm not going to try to list them all here now. You'll learn them as you run across them.

Also, note that objects don't have names.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My language was incorrect. I understand the constructor ( method with the same name as the class that is called when the class is created ). What I was talking about was the variables that the constructor loads that are available to the class.

I know about overriding and overloading, the class I made was overriding the method in the abstract parent class.

A local variable (of which method parameters are a subset) can have the same name as a member variable. A member variable in a child class can have the same name as a member variable in a parent class, but this is a really bad idea.


Yes, your answer here is what I was asking about. Other naming practices that are bad but that are legal and would not throw a compiler error.

Thank you again for all your help today.
 
margaret gillon
Ranch Hand
Posts: 335
6
Linux Tomcat Server Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jeff,

Also, note that objects don't have names.


Yes... I redact my language on that, too.

Objects don't have names. Variables have names. Note that a variable is not the same as an object; a variable is a reference to an object. You can have multiple variables that refer to the same object. Jesper de Jong, Java Cowboy, Bartender
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!