Java how and where to initialize variable with NullPointerException - java

I'm having a problem where I receive this error:
Exception in thread "main" java.lang.NullPointerException
at com.noxia.Main.startCombat(Main.java:101)
at com.noxia.Area1.createArea1Enemy(Area1.java:43)
at com.noxia.Main.main(Main.java:30)
I know that I need to initialize the variables because they are null, but I can't seem to figure out what I need to put where. I've minimized the code to show just the relevant parts as there are many other variables and methods left out, but this seems to pertain to the issue. Any help would be greatly appreciated =)
public class Main {
Player p;
Enemy e;
Area1 a1;
public static void main(String[] args) {
Main main = new Main();
main.a1 = new Area1();
main.p = new Player(100);
//the line directly below this is line 30 where the error occurs
main.a1.createArea1Enemy(10);
}
public void startCombat()
{
//the line directly below this is line 101 where the error occurs
while (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
p.playerAttack();
if (p.getCurrentLife() > 0 & a1.e.getLife() > 0)
{
e.enemyAttack();
}
}
}
public class Player extends Main {
private int currentLife;
public int getCurrentLife()
{
return currentLife;
}
public void setCurrentLife(int cl)
{
currentLife = cl;
}
public Player(int cl)
{
currentLife = cl;
}
public class Enemy extends Main {
private int life;
public int getLife()
{
return life;
}
public void setLife(int lf)
{
life = lf;
}
public Enemy (inf lf)
{
life = lf;
}
public class Area1 extends Main {
public void createArea1Enemy(int enemyCounter)
{
while (enemyCounter > 0)
{
String[] enemyList = {"Enemy1", "Enemy2"} //code for Enemy2 left out below
int enemyListLength = enemyList.length;
int randomEnemy = (int) (Math.random() * enemyListLength);
if (enemyList[randomEnemy].equals("Enemy1"))
{
Enemy enemy1 = new Enemy("Enemy1", 100);
//the line directly below this is line 43 where the error occurs
startCombat();
}
enemyCounter--;
}
}
}

The simple answer is that you have to set e to an enemy before calling startCombat.
But a better way to do this would be to remove e, and pass the enemy object to startCombat using a method parameter. The e field is conceptually wrong. To understand the wrongness, try to come up with a coherent explanation of what it means in terms of the state of a Main object.
Clearly this is beginner code ... and there are a number of bad things about what you have written:
The fields of a class should be for object state, not for passing parameter values to methods.
You should avoid writing code that accesses the innards of a class ... like your main method does.
Best practice is to make fields private, and defined getter and / or setter methods (as required) for external classes to access / modify them.
You need to learn how to write constructors with parameters.
You need to design your code properly. Everything extending Main means that there is going to be no rational model of what the objects "mean". And there's the problem that each instance of Enemy and Area1 will have their own copies of the p, e, and a1 fields, and a whole bunch of inappropriate methods.

The main problem is that you never initialize Enemy e;. You create an enemy but never assign it to this.e.
Change this line:
Enemy enemy1 = new Enemy("Enemy1", 100);
To this:
this.e = new Enemy("Enemy1", 100);
There are also many other problems with your code.

Learn how to write a constructor properly. This code is wrong.
I see no reason at all why a Play, Area1, and Enemy should extend Main.

Related

java ConcurrentHashMap with constructor as key

I am currently trying to write a little game in java lwjgl/OpenGL.
When running the code i get the value NULL when reading from some ConcurrentHashMap.
I've written a simple program to reproduce the same issue and sure enough, i could.
Let me show the code to you:
The Program consists of three classes.
The Main class:
package main;
public class Main {
private MapContainer con = new MapContainer();
public static void main(String[] args) {
new Main();
}
public Main() {
ValueContainer vc = new ValueContainer(1, 2, 3);
this.con.set(vc, "Just a String");
System.out.println(this.con.get(vc));
}
}
Then there's the MapContainer class.
It's basically a class that contains a ConcurrentHashMap and two methods to access it:
package main;
import java.util.concurrent.ConcurrentHashMap;
public class MapContainer {
private ConcurrentHashMap<ValueContainer, String> map = new ConcurrentHashMap<>();
public void set(ValueContainer key, String value) {
this.map.put(key, value);
}
public String get(ValueContainer key) {
return this.map.get(key);
}
}
At last, there's the ValueContainer.
This class just contains the three Integers x, y and z, and a Constructer to set these values.
package main;
public class ValueContainer {
public ValueContainer(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int x, y, z;
}
So when i run the main class, i create a new ValueContainer with the values 1, 2, 3 and put it into the map Container, along with the String "Just a String".
Then i read the String with that exact Value container and print it out.
Sure enough the program works and i get "Just a String" printed in the Console.
So now there's my game:
In my game i have to access a similar ConcurrentHashMap, but i cant use the same ValueContainer to access the String, but i have to create a new one with new ValueContainer(1, 2, 3);
So obviously the ConcurrentHashMap can't give "Just a String" back, because it's not the same ValueContainer, so it gives NULL.
Here's the code of the Main class with this little modification:
package main;
public class Main {
private MapContainer con = new MapContainer();
public static void main(String[] args) {
new Main();
}
public Main() {
this.con.set(new ValueContainer(1, 2, 3), "Just a String");
System.out.println(this.con.get(new ValueContainer(1, 2, 3)));
}
}
Now my question:
Is there any way for me to use the version in the second main class, but without the issue, so that i
get printed out "Just a String" in Console?
Thank you.
Yes, quite simple.
You have to override the two methods Object.hashCode() and Object.equals() in your class ValueContainer.
Please take a look add the API-documentation of the two methods.
API
Maybe you use a IDE like Ecplise oder IntelliJ which will help you with the details.

Java - changing a variable through pass-by-value

So I've read about the pass-by-value nature of Java and I've tried to change my variable after passing it to a function by having the function return the variable again. I didn't succeed in that.
My code
public class Logic {
private int position;
public class Logic(){
position = 1;
}
public void appendPosition(){
position = calculatePosition(position);
}
}
This is the barebones code. I call this method from an instance of Logic which is instantiated in another class:
public class MainLogic {
ILogic L;
public MainLogic(ILogic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
}
Through repeated debugging I find to my dismay that the position variable does not change at all. The position variable passed to calculatePosition changes fine, as expected. What am I missing? I've tried making the variable public and static.
calculatePosition
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations = new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
public class Logic {
private int position;
public Logic(){
position = 1;
}
//to get position.....................
public int getPosition(){
return this.position;
}
public void appendPosition(){
position = calculatePosition(position);
}
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations =
new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations =
new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
}
//next class
public class MainLogic {
Logic L;
public MainLogic(Logic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
public static void main(String[] args) {
Logic L = new Logic();
MainLogic ml = new MainLogic(L);
System.out.println(ml.L.getPosition());
ml.start();
System.out.println(ml.L.getPosition());
}
}
Let's read your code.
// There is a logic class.
public class Logic {
// So Logic has a position. it starts with zero.
private int position;
// Logic also has an inner class, also called Logic.
public class Logic(){
position = 1;
// When a new Logic().Logic() is created, the instance
// variable of the parent instance gets set to one. WHAT?!?
}
// ... lots of code
}
So, It's a bit like that Yo Dawg! meme - I heard you like Logic, so we've put A logic instance into your Logic instance so you can Logic while your Logic.
You probably want a constructor.
// So this is Logic.
public class Logic {
private int position;
// When an Logic instance is created, position starts with 1.
public Logic(){
this.position = 1;
}
Ok. So we're not talking about Yo Dawg Memes.
So Let's talk pass by value.
Pass-by-value means classes are like very egotistic children: You can't play with their toys, unless they tell you so.
This is a good thingĀ® since this means only the owning instance is allowed to change their private state. Trust me, it prevents quite a bit of havoc.
One way to allow the outside world to actually change the state is by using query and mutator methods. Back in the day, we used to call them getter and setter, but that sounds too simple, so software architects will usually use the fancier term.
But... all of this doesn't really apply since calculatePosition() is defined at Logic. Oops.
Let's try this:
Renaming some instance variables
Be a bit verbose to help the debugger. baby steps.
(Also, dropping a few jokes to fish for upvotes).
public class Logic {
private int position = 1;
public void appendPosition(){
// When debugging strange stuff,
// keep each step simple.
// Is calculatePosition working as it should?
int newPosition = calculatePosition(this.position);
this.position = newPosition;
}
// Always use parameters as final. It's good karma.
// You don't NEED to declare them as final,
// but let's try to be EXTRA clear.
private int calculatePosition(final int targetPosition){
// Yes, make as much as you can immutable
// You'll save a ton of mental bandwidth.
final int localCopy = targetPosition +6;
if(snakeLocations[localCopy]>0) {
return (localCopy -6);
// Don't force the maintenance programmer to
// read all your stuff. Return often, return early.
// This isn't Cc++, where you need to
// actually free your reference/pointers,
// so there's no point enforcing a single return.
}
if(ladderLocations[localCopy]>0) {
return (localCopy+6);
}
return localCopy;
}
}
So... Did this worked as it should?
I found the answer. This is often my mistake in posting here. I try to strip down my code as much as possible to ease the work for you guys, but sometimes the problem lies outside of the scope of what I provide due to a lack of understanding, or oversight, on my part.
I was actually calling MainLogic from two levels above:
public mainFrame() {
initComponents();
logic = Factory.getMainLogic();
}
where
public static class Factory {
public MainLogic getMainLogic(){
PlayerLogic pL = new PlayerLogic();
ImageLogic iL = new ImageLogic();
DieLogic dL = new DieLogic();
MainLogic mainLogic = new MainLogic(pL,iL,dL);
return mainLogic;
}
}
I forgot I had accidentally put Factory as static. My sincerest apologies for wasting your time.

How to change jlabel text from another class

Hi I'm making an app but, I found a problem. I'm using netbeans gui builder to build my gui.
So, the first gui class has a lot of button(every button does the same function) that have an actionlistener that looks like this:
public class Guipanel extends JPanel {
private void jbtTTActionPerformed(java.awt.event.ActionEvent evt) {
if(mb.getlevel() > 16){
if(ttp != 20 && mb.getpoints() != 0){
point();
ttp++;
jbtTT.setText(""+ttp);
}
}
}
private void point(){
mb.reducepoints();
}
int ttp;
Base mb = new Base();
JButton jbtTT = new JButton();
}
The Base Class has a lot of method but the one that is related to this problem looks like this:
public class Base extends JFrame {
//point decrement method
public void reducepoints(){
points--;
jlbPoints.setText("Points Available: "+points);
}
//return point value
public int getpoints(){
return this.points;
}
//return level value
public int getlevel(){
return this.level;
}
private static int level = 1;
private static int points = 20;
private JLabel jlbPoints = new JLabel("Points Available: "+points);
}
So the problem is this, when I pressed the jbtTT the points variable will decrement so the value will change from 20 to 19. I used System.out.println to verify that. As you can see, the reducepoints() method should update the jlbPoints text which it doesnt. I have tried making the Base mb = new Base() to static Base mb = new Base() but it still doesn't work. Am I doing this wrong? Anyone have a suggestion?
EDIT: I've tried to do System.out.println(jlbPoints.getText()); and the text did changed. The only one that didn't change is the text that the user can see. Even repaint() and revalidate didn't work.
EDIT2: I finally found the answer to this question. I have to pass the 'Base' class object to the 'Guipanel' class since I created the 'Base' class object in a main class(I don't want to use this class as a main class). I passed it with the following method:
public void passObj(Base mb){
this.mb = mb;
}
and changing the constructor of 'Guipanel' class like this:
public Guipanel(Base mb) {
initComponents();
this.mb = mb;
}
also changing this Base mb = new Base(); to Base mb;
I wanted to thank everyone that have tried to answer this question.
Try using SwingUtilities.invokeLater() to ensure you are changing the text on the event dispatch thread, as you are supposed to. All we can do is guess given the current information.

Calling a method from JFrame from another class

I am currently making a terrain generator, everything works fine in one class but I am going to be expanding my application.
Currently I have a JFrame class which holds everything, generating the terrain, painting the terrain, finding locations etc.
I want to add another class that will generate the terrain but when I create this class I need to access fields from the main JFrame class and when I do I get a stack overflow error - here is my code.
public class Simulator extends Applet
{
//fields
public Simulator()
{
grid = new int[100][100];
inhabGrid = new boolean[grid.length][grid.length];
gridSize = grid.length - 1;
dist = grid.length;
TerrainGenerator gen = new TerrainGenerator();
setSize(dist,dist);
seedGrid();
findInhabLocation();
printGridToConsole();
}
public void paint(Graphics g)
{
//panting the grid
}
public void seedGrid()
{
//seeding
}
public boolean generateTerrain(int x1,int y1, int x2, int y2)
{
//terrain generator
}
public boolean mouseUp(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public boolean keyEvents(Event evt, int x, int y)
{
seedGrid(); //Create a new map
findInhabLocation();
repaint();
printGridToConsole();
return true;
}
public void findInhabLocation()
{
//find best inhabitant location
}
public int locateWater(int x, int y)
{
//finding closest water
}
public int locateJungle(int x, int y)
{
//finding closest jungle
}
}
}
That works fine in its own class but when I create a class for example:
public class TerrainGenerator
{
Simulator sim = new Simulator();
}
I know this has something to do with the constructor and it's something silly I am doing, what would be the best way of splitting up this app into classes, for example terrain generator, inhabitants etc
For example I want to be able to call a method from the 'TerrainGenerator' class and call i.e. terrainGenerator.generateTerrain
Your TerrainGenerator creates a Simulator object and vice versa, hence you'll end up with infinitely many objects (but at some point the stack is full and a stack overflow exception is thrown instead...)
Instead of creating a new Simulator in your TerrainGenerator, you should pass a reference to your current Simulator (well, actually, that is not a great design either, but I'm not gonna confuse you with the problems of circular references).
Heuster answer is correct, furthermore, I think you could take look at MVC to help you organize your classes.
Depending which should be the parent, you can pass in the instantiated class to the other, ie;
private final TerrainGenerator gen; //if you need to save this.
public Simulator(TerrainGenerator terrainGenerator)
{
this.gen = terrainGenerator;
....etc
}
public class TerrainGenerator
{
Simulator sim = new Simulator(this);
}
or
private final TerrainGenerator gen; //if you need to save this.
public Simulator()
{
this.gen = new TerrainGenerator(this);
....etc
}
private final Simulator sim; //If you need to save it.
public class TerrainGenerator
{
public TerrainGenerator(Simulator simulator) {
this.sim = simulator;
}
}

How can I use the Command Pattern in Java like I do in C++?

I was working on a game recently in C++ where I implemented the Command Pattern to manage keyboard input to control a spaceship. When instantiating all the commands, I'd pass the spaceship pointer to each constructor so all commands were working with the same spaceship object.
This pattern made sense in C++ because you can pass by reference, but in Java everything is pass-by-value. If I tried to implement the same thing in Java, how would I have each command pointing to the same object?
In all the examples I've seen of the Command Pattern used in Java it makes no difference whether the member variables of each Command are copies or references.
Java does pass by value in all cases, however all 'non-primitive' types exist as references, so for types like String, List or Spaceship you're actually passing a reference around - the pass by value is because you're passing the reference by value. Which is a pretty confusing way of expressing it, I always felt.
Anyway, the upshot of it is that if you have a (hugely simplified) Command class
public class Command {
private Spaceship spaceship;
public Command(Spaceship ship) {
spaceship = ship;
}
}
And then you do this:
Spaceship ship = new Spaceship();
List<Command> ships = new List<Command>();
for (int i = 0; i < 40; i++) {
ships.add(new Command(ship));
}
then every single one of those Command objects has a reference to the same Spaceship object. Passing the reference by value does not cause a copy of the Spaceship object that the reference points to. However, if you were passing ints around, you would indeed be passing copies.
Just remember the distinction between primitive types like int, and object types like String and you'll be fine. It's helpful to remember that primitive type names begin with a lowercase letter (and can never be user-defined), while object types begin with a capital letter. All user-defined types are object types.
Thanks for your help guys. At the end of the day it came down to my complete misunderstanding about how Java works. I was under the impression (for some strange reason) that creating a Command and giving it my object meant that it received a copy instead of a reference to the original. If that was the case then calling .execute() in a Command would have had no effect on the object outside of the class.
Yet, I found that this was not the case after creating a small test:
Sprite.java:
public class Sprite {
private int x;
Sprite(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
Command.java:
public interface Command {
void execute();
}
MoveLeftCommand.java:
public class MoveLeftCommand implements Command {
private Sprite s;
MoveLeftCommand(Sprite s) {
this.s = s;
}
public void execute() {
s.setX(s.getX() - 1);
}
}
MoveRightCommand.java:
public class MoveRightCommand implements Command {
private Sprite s;
MoveRightCommand(Sprite s) {
this.s = s;
}
public void execute() {
s.setX(s.getX() + 1);
}
}
Test.java:
import java.lang.*;
import java.util.*;
public class Test
{
public static void main(String[] args) {
Sprite mario = new Sprite(0);
Command command = null;
Map<String, Command> commands = new HashMap<String, Command>();
commands.put("a", new MoveLeftCommand(mario));
commands.put("d", new MoveRightCommand(mario));
// Test...
System.out.println(mario.getX()); // 0
command = (Command) commands.get("a");
command.execute();
System.out.println(mario.getX()); // -1
command.execute();
System.out.println(mario.getX()); // -2
command = (Command) commands.get("d");
command.execute();
System.out.println(mario.getX()); // -1
}
}
I correctly saw 0 -1 -2 -1 in the console, just as I would have in C++.
In java they passed "by value"... You pass real object that will implement an execute method. Sharing reference among different objects can be achieved by proper OO design or lookup method injection for common attribute. The Command pattern example was taken from wikipedia
/*the Command interface*/
public interface Command {
void execute();
}
/*the Invoker class*/
import java.util.List;
import java.util.ArrayList;
public class Switch {
private List<Command> history = new ArrayList<Command>();
public Switch() {
}
public void storeAndExecute(Command cmd) {
this.history.add(cmd); // optional
cmd.execute();
}
}
/*the Receiver class*/
public class Light {
public Light() {
}
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
/*the Command for turning on the light - ConcreteCommand #1*/
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight = light;
}
public void execute(){
theLight.turnOn();
}
}
}
Since Java always does pass by value, you will need to do something mutable to pass through instead (pass a mutable object).
Consider this example:
In this agnostic language that supports pass-by-reference
string commandArg = "";
new StringCommand().execute(commandArg);
Console.write(commandArg);
And in StringCommand.execute(string arg), you have arg += "Hello World", then your output will be Hello World.
In Java, simply pass a StringBuilder as follows:
StringBuilder sb = new StringBuilder();
new StringCommand().execute(sb);
System.out.println(sb.toString());
where StringCommand.execute(StringBuilder sb) contains:
sb.append("Hello World");
The StringBuilder reference is passed by value in StringCommand.execute. In a nutshell, primitive types are passed by value and, for objects, the reference of the object is passed by value.
I hope this helps.

Categories