• Post Reply Bookmark Topic Watch Topic
  • New Topic

Null pointer exception  RSS feed

 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure I understand why this is showing up as a NullPointerException. There's another class set up in a similar way that works, the only real difference is that it only has one number inside the parenthesis for each enum instead of two. Originally this worked when I created a new Monsters object by setting it's class type to Participants instead of Monsters, but since changing it it seems to have broken everything.

In the GameManager class this was

then I changed it to this...

and now it's broken.

In the GameManager class I am setting up an array of Room objects so that each contains a monster and weapon (some of which may just be empty objects because I was told not to use null)


that calls to a monster spawner method


and then a new monster is created in the Monsters class...


in Rooms class:


I don't have a lot of experience with enums, actually creating multiple 'types' of monsters using the Monsters class is just an extra challenge that I wanted to try and doesn't necessarily have to be done with enumerated types. I could have simply went with the bare minimum and made one default monster only, but I wanted to try to push myself a bit.
I tried to run the Eclipse debugger but am still not sure why it's not setting up Type, if that is in fact where the problem lies. Before I changed the monster object type in GameManager from Participants to Monsters it worked fine, but I think that it was basically just skipping over everything in the Monsters class, so based on that and the error output I think the issue is with the toString in Monsters. I'm still not very familiar with using a debugger, it's something we were left to figure out on our own, but if I was understanding it correctly, it didn't seem like Type was being set to anything, but again when I had that object set with Participants it worked fine and displayed the correct enum name and everything worked as intended. The toString in this method is set up the same way its set up in a similar method (a Stick class and a Sword class, each of which inherit from a Weapons class), and that one works, and again the only difference is that the other one only has one number in the parenthesis for the enum to set the damage for each enum 'type' of sword or each 'type' of stick. Is there something I'm not understanding about enumerated data types?


Exception in thread "main" java.lang.NullPointerException
at game.Monsters.toString(Monsters.java:104)
at game.Rooms.toString(Rooms.java:128)
at game.GameManager.toString(GameManager.java:216)
at java.lang.String.valueOf(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at game.Driver.main(Driver.java:50)



Line 104 in Monsters:


Line 128 in Rooms:

 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are creating a lot of cognitive dissonance with names that don't follow normal naming conventions.  That makes those of us who are used to following the conventions work harder to understand your program.  For example, monsterType is an enum type and Type is an instance variable of that type.  The case is backwards in both names. It should be MonsterType and type, respectively.  While you're at it, you might want to spell out the hp and atk field names.  Don't abbreviate field names like that because it makes your code much harder to read. Make your program names pronounceable.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As I was telling another forum member in a different thread, issues with names may seem trivial to you but they are actually very important and key to your program's clarity and expressiveness. If your program is not clear or expressive, it's more difficult to understand and follow the logic. Code that's difficult to follow and understand is difficult to debug and validate just by reading it because your brain is working overtime to overcome the cognitive dissonance that obscures the code's intent.  Class names, for example, are normally singular, not plural. In the case of your Monsters class, it should be just Monster since an instance of this class represents only ONE monster, not several monsters.  Same thing for Participants; it should be singular, not plural.
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One other small question:

I have this set in a for loop...


but could simply do this and cut out extra steps:


I didn't set it up the second way because I've been told that's a bad way of doing things and have been docked points for doing similar things. Instead I was told to always set method calls to a variable first before passing whatever value is returned someplace else rather than putting a method call directly into something such as a constructor or even in a println statement if the method call is set to return a string. I was told to instead call the method and store its return value into a variable and then run a print on that variable. So is one way better than the other? Good practice or bad?
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your class has two constructors, one that takes no arguments and another that takes two arguments. The type field is set only in the latter constructor. The no-argument Monsters() constructor doesn't set the type field, so any instance that was created using the no-argument constructor might still have a null type field when you call the toString() method. That is what causes the NullPointerException.
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:Class names, for example, are normally singular, not plural. In the case of your Monsters class, it should be just Monster since an instance of this class represents only ONE monster, not several monsters.  Same thing for Participants; it should be singular, not plural.
I didn't have any control over the class names. I simply named them what I was instructed to name them. The enum thing however, was my fault.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:
Junilu Lacar wrote:Class names, for example, are normally singular, not plural. In the case of your Monsters class, it should be just Monster since an instance of this class represents only ONE monster, not several monsters.  Same thing for Participants; it should be singular, not plural.
I didn't have any control over the class names. I simply named them what I was instructed to name them. The enum thing however, was my fault.

Are you sure you were told to name those classes Monsters and Participants? Not that I don't believe you or anything but I'd still like to "trust but verify."  Can you paste in your instructions exactly as they were given to you, particularly, the part that tells you to use those names? I just want to see it with my own eyes and make my brain accept something that it's having a hard time understanding, how something like that could come from a university professor. Thanks.
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I misread. I think Monsters caught my attention as a class name in the instructions because it was capitalized.


Derive 3 types of Monsters (for example, Cyclops, King Kong, and Frankenstein) from
the Monster class, each with its own number of health points and its own amount of
damage it can inflict.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:I didn't set it up the second way because I've been told that's a bad way of doing things and have been docked points for doing similar things. Instead I was told to always set method calls to a variable first before passing whatever value is returned someplace else rather than putting a method call directly into something such as a constructor or even in a println statement if the method call is set to return a string. I was told to instead call the method and store its return value into a variable and then run a print on that variable. So is one way better than the other? Good practice or bad?

Standard consultant's reply: It depends.

I know where the "that's a bad practice" school of thought comes from. It's from folks who don't know how to write simple code. One attribute of simple code is that its parts are small. Small methods means up to 5 lines on average.  If you write code that has chunks that are 30 lines of code on average, then that's not simple.  If you write code in that shortcut way, invoking methods inside method calls instead of on a separate line then assigning them to temporary variables, then debugging your code when it has problems can get very difficult very quickly. That's why many people consider it a bad practice, because it makes bad code even worse.

On the other hand, if you write simple code that's small, you can make your code more streamlined and less cluttered by inlining the method calls.  If the method names are descriptive and the method implementations are small, then there's really no reason to create temporary variables to hold intermediate results.

One confusing thing that novices will find in Martin Fowler's book Refactoring: Improving the Design of Existing Code is that seemingly contradictory refactorings are listed in the catalog. For example, there's "Eliminate Temporary Variable" refactoring. Then he turns around and gives you "Introduce Explaining Variable" which looks a lot like you're creating a temporary variable.

The way to reconcile these seemingly contradictory pieces of advice is to understand the context in which they are appropriate to use.  In the same way, you should understand the context in which the advice to use temporary variables as "good practice" is given.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:I misread. I think Monsters caught my attention as a class name in the instructions because it was capitalized.

Derive 3 types of Monsters (for example, Cyclops, King Kong, and Frankenstein) from
the Monster class, each with its own number of health points and its own amount of
damage it can inflict.

Ok. For future reference, let's play it safe and verify any future assumptions you're making against the exact instructions you've been given. We don't want to put your instructor in a bad light if it's not actually fair to do so.

These instructions tell you to Derive 3 types of Monsters. When you're told to "derive" some types, that usually means you're supposed to extend a base class. In this case, the base class is Monster. I'm not sure defining an enum really qualifies as a valid interpretation of those instructions.  You might want to run this by your instructor to make sure you're on the right track with the enum, before you get too far along and it gets more and more difficult to switch gears and head in a different direction with your design.
 
Nikki Smith
Ranch Hand
Posts: 65
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
These instructions tell you to Derive 3 types of Monsters. When you're told to "derive" some types, that usually means you're supposed to extend a base class. In this case, the base class is Monster. I'm not sure defining an enum really qualifies as a valid interpretation of those instructions.  You might want to run this by your instructor to make sure you're on the right track with the enum, before you get too far along and it gets more and more difficult to switch gears and head in a different direction with your design.


I asked about that earlier and got the 'ok' to do so. I also had to make sure it was ok that I put the enums inside of the Monster class. Usually we're told that we're to have enums listed in their own separate class.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
On the other hand, deriving a KingKong class from a Monster base class is kind of a smelly design choice to me. There are potentially hundreds of different types of Monster you can think of, from Godzilla to The Swamp Thing. Heck, just the Monsters, Inc. movie alone could give you at least a dozen different types of Monster derivations. Sully, Mike Wazowski, Randall Boggs, all were different types of Monster. Does that mean you'd have to create a new subclass for each new type of Monster? That doesn't sound right. I'm not sure I agree with how those instructions were worded but then again, you're the one who's being graded for this work so maybe you should go back to your instructor and discuss this concern with him, if you're so inclined. Otherwise, just keep in mind that this might not be a very well thought-out design he's asking you to implement.

A derived class is a specialization of its superclass. That's why we try to avoid using the term "parent" and "child" classes in these forums, because the connotation of parent-child is different from the more apt generalization-specialization definition of the relationship between a superclass and its subclasses.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nikki Smith wrote:I asked about that earlier and got the 'ok' to do so. I also had to make sure it was ok that I put the enums inside of the Monster class. Usually we're told that we're to have enums listed in their own separate class.

Again, it comes back to creating context. By defining the enum inside the Monster class, your design is declaring a tight relationship between Monster and Type, such that this enum type is to associated only with the Monster class and nothing else. I think those are good semantics to establish in this case. There are different contexts where it might be best to define an enum type as it's own separate and independent type.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!