Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

A Basic Question (About Classes)  RSS feed

 
Biju Mathew
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,
Ive started learning Java using Head First Java by Kathy Sierra & Bert Bates. I wanted to clear something before continuing so would appreciate some help here. On Page 39 (Program GuessGame) the following code is given.



If I were to comment out the lines in bold I would get the following error.
Exception in thread "main" java.lang.NullPointerException .....
Would appreciate an explanation on what Player p1; represents and what p1 = new player(); represents.

Can I write the above code as shown below :



I wrote the above code and the program works fine. However is this a good programming practice? Is there a certain reason why the code at the top was written as it was?

Thanks in advance.
Biju Mathew
[ August 14, 2007: Message edited by: Biju Mathew ]
 
David McCombs
Ranch Hand
Posts: 212
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
p1 is a reference to a Player object. p1 mere stores where the object can be located. The HF book will later go into more details about where references and objects live.

I don't think the first code example is good programming practice. It is OK to declare references as class level but the class level references should be created in the constructor, not some method.

The second example is a little better, but again the objects should be created in the constructor. That is why the constructor exists, to set up the object.
[ August 14, 2007: Message edited by: David McCombs ]
 
marc weber
Sheriff
Posts: 11343
Java Mac Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm not so sure this is a black and white situation. Certain guidelines might be appropriate in a general sense, but ultimately it depends on the context.

For example, if these Player instances are created without any special parameters, then wouldn't it be safer to instantiate them in the declaration line so that they are available to a GuessGame constructor? (That's my preference.) On the other hand, do we know that all of these Player instances will be required in an instance of GuessGame? In other words, does it make sense to create objects whether or not they will ever be needed? Further, are there ways to do anything with these Players before calling StartGame? Doesn't it make sense that starting a new game would be the time to create Players? Consider that this method might also act as a "reset" to instantiate new players without creating a new game instance.

So, it all depends. The important thing is to ensure that the variables are instantiated before trying to use them, but this can be accomplished in different ways.
 
Biju Mathew
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for your help. That helps . I guess a bit more reading into the book will also help .
 
Justin Samuel
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes Biju,
There is definitely some purpose and thought given in the first case. Definitely what you have done in the second case is also right.But that is not a good way of doing it.

See,in the first case the three statements (Player p1 really means that they are just reference variables(to show that these variable belong to that particular class). In other words memory to these variables are not yet allocated. But once you write the statement (p1 = new Player() .....done in StartGame() function), it means that object are created and these reference variable starts pointing to those objects.......Thus memory is allocated only within the function itself and released as soon as scope of that objects are finished after existing from that function. That is not the case in the second one where you have allocated the memory on heap for the entire time period.

Now there may be a question from your side, why not write the complete sentence (like .. Player p1 =new Player() within that function itself ...... that is also fine............but you cannot access that reference variable outside that function............which is actually now possible as it has been declared as class variable not variable within methods.....

If you have more doubt please feel free to clear those out!

Hope my answer satisfies your question....

Regards,
Justin Samuel
 
Raghavan Muthu
Ranch Hand
Posts: 3389
Mac MySQL Database Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It certainly depends on the situation and context as marc said.

I would like to quote an instance where you need to declare the variable first (probably outside) and initialize (make use) it later. In case of try-catch blocks



If you have declared and initiialized the Conneciton object inside the try block in a single statement, you will not get it in the finally block as the SCOPE of it is limited to the block where it is defined.

Hope this adds some value and you are clear with the difference between Reference Vs Objects.

In K & B's book itself a nice example they would have given as "TV" is the actual object and the "Remote Control" is the reference to it through which you can access and control the *actual* objects.
[ August 17, 2007: Message edited by: Raghavan Muthu ]
 
Greg Messer
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I came here looking for something else, but found this nugget talking about the first code shown:

Thus memory is allocated only within the function itself and released as soon as scope of that objects are finished after existing from that function.


It is true that the "memory is allocated only within the function itself". But in the code from the book, the first version of the code shown, the memory allocated for the field inside the function would not be freed "after exiting from that function". It would only be eligible to be freed when the instance of the GuessGame object went out of scope. Only allocations whose references are stored in local variables inside the StartGame() function would be freed when StartGame() ended, not allocations whose references are stored in class member variables. The variable holding the reference to the memory has to go out of scope before the memory can be garbage collected.

In the code from the book, the memory for the three player objects will be eligible to be freed when the GuessGame object goes out of scope - which happens when the main() function in the GameLauncher class ends.

I'll try to answer the question about why it was written this way. The main function in GameLauncher could be extended to run the game until the user decides to quit. Or, new functions could be created to start two-player and one-player games. A new method could be added to GuessGame, perhaps called reInitGame(), that could free the memory for the player objects that are not null because they were previously allocated. This is a simple example program, but if creation of players was expensive, because it required a database access or login verification or something like that, then delaying the allocation and deallocation until it is absolutely necessary is a wise move. If successful games where the number was guessed correctly were important, then freeing and reallocating players might include saving scores, player names, timestamps, etc.

So if the allocations were done at the class level, the flexibility to extend the behavior of the program would be affected.

Greg
[ August 21, 2007: Message edited by: Greg Messer ]
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!