Jump to content
Science Forums

Help with Java


Recommended Posts

Well, I've been trying to solve this for a week, with no success. I'm trying to use a dynamically created array. The declaration is at the class scope, the instantiation is done within a function during runtime. The problem is that I get Null Pointer Exceptions when other functions attempt to access it. Here's the code:

 

public class Building 
{
   private int LeftX, RightX, MaxY, XBrick, YBrick;
   private BuildingBlock bricks[][];
   
   /** Creates a new instance of Building */
   public Building() 
   {
       LeftX = 0;
       RightX = 0;
       MaxY = 0;
   }
   
   //accessors
   public int GetLeftX(){return LeftX;}
   public int GetRightX(){return RightX;}
   public int GetMaxY(){return MaxY;}
   
   //initializer
   public void SetPosition(int a, int b, int c)
   {
       LeftX = a;
       RightX = b;
       MaxY = c;
               
       XBrick = (RightX - LeftX) / Globals.BLOCK_WIDTH;
       YBrick = MaxY / Globals.BLOCK_HEIGHT;
       
       BuildingBlock bricks[][] = new BuildingBlock[XBrick][YBrick];
       
       //instantiate all bricks
       for(int x = 0; x < XBrick; x++)
       {
           for(int y = 0; y <= YBrick - 1; y++)
           {
               bricks[x][y] = new BuildingBlock();
               bricks[x][y].SetPosition(x * Globals.BLOCK_WIDTH, y * Globals.BLOCK_HEIGHT);
           }
       }
       //make sure all bricks are intact
       for(int h = 0; h < XBrick; h++)
       {
           for(int v = YBrick - 1; v >= 0; v--)
           {
               try 
               {
                   bricks[h][v].Intact();                    
               } 
               catch (NullPointerException e) 
               {
                   System.out.println("H:" + h + " V:" + v);
                   System.out.println("XBrick:" + XBrick + " YBrick:" + YBrick);
               }
           }
       }
   }
   
   public boolean Collision(Point p)
   {
       //If not within the building's limits
       if(p.x < LeftX || p.x > RightX || p.y > MaxY)
       {
           return false;
       }
       
       //System.out.println("HERE");//diagnostic
       
       //test all bricks, left to right, top to bottom
       for(int h = 0; h < XBrick; h++)
       {
           for(int v = YBrick - 1; v >= 0; v--)
           {
               //System.out.println("H:" + h + " V:" + v);//diagnostic
               if(bricks[h][v].Intact()) //***HERE'S WHERE THE EXCEPTION OCCURS***
               {
                   
                   if(bricks[h][v].Collision(p))
                   {
                       return true;
                   }
               }
           }
       }
       
       return false;
       
   }
   
}

 

The error occurs in the last function - Collision, at the test of bricks[h][v].Intact()

Link to comment
Share on other sites

Dave, make sure that that YBrick has a value when you are referring to it in the method. i mean if it does not, or it has a value of 0, then when you subtract one from it it will turn into a negative number, that would definitely create an issue... i'd start there

 

i'll look over your code sometime later on today (shoot its 1am again)

Link to comment
Share on other sites

Can't see the BuildingBlock class, and its failing inside that class, inside the Intact method, unless....

 

Why do you allocate the size of the BuildingBlock array inside of SetPosition? Traditionally, you should allocate all dyanmic memory for an object when you instantiate it (i.e. inside of the Building() method). You could have a good reason for doing this, but I don't see it. If Collision is called before SetPosition, then the null ptr error is going to come as soon as you try to reference the array indices and before Intact is actually called.

 

Try putting a try-catch around the line that's breaking inside of collision, just like you have in SetPosition, then you can print the variable.

 

What are you using to develop it? I really can't imagine programming without a debugger, and if you're not using one where you can set a breakpoint at that line and inspect all the variables, well, you get what you deserve! :turtle:

 

Hope this helps! Keep asking questions!

 

Watching variables,

Buffy

Link to comment
Share on other sites

I'm allocating the size of BuildingBlock inside of SetPosition because I'm using an array of five Buildings, then determining their size before each board is loaded. Collision isn't called before SetPosition. I'm using NetBeans...but I don't know how to use the debugger...I've never needed to use a debugger before.

 

The Intact meathod simply returns a boolean variable, so I don't think that it's failing there.

 

For reference, here's BuildingBlock:

public class BuildingBlock 
{
   private boolean stillintact;
   private int LX, RX, UY, LY; //Left X, Right X, UpperY, LowerY
   
   /** Creates a new instance of BuildingBlock */
   public BuildingBlock() 
   {
       stillintact = true;
       LX = 0;
       RX = 0;
       UY = 0;
       LY = 0;
   }
   
   //Accessors
   public boolean Intact(){return stillintact;}
   public int LeftX(){return LX;}
   public int RightX(){return RX;}
   public int UpperY(){return UY;}
   public int LowerY(){return LY;}
   
   //initializers
   public void SetPosition(int x,int y)
   {
       LX = x;
       RX = x + Globals.BLOCK_WIDTH;
       LY = y;
       UY = y + Globals.BLOCK_HEIGHT;
   }
   
   public boolean Collision(Point p)
   {
       if(!stillintact)
       {
           return false;
       }
       if(p.x < LX || p.x > RX || p.y < LY || p.y > UY)
       {
           return false;
       }
       
       stillintact = false;
       return true;
       
   }
   
}

Link to comment
Share on other sites

  • 1 year later...

Dave, you have two declarations of the same variable.

 

you declare globally:

private BuildingBlock bricks[][];

 

you declare locally:

BuildingBlock bricks[][] = new BuildingBlock[XBrick][YBrick];

 

I maybe mistaken in this, but I believe you need only declare the variable once, so your instantiation would be as follows:

bricks[][] = new BuildingBlock[XBrick][YBrick];

Link to comment
Share on other sites

i dont think that's it, KAC, its a standard procedure in OOP to declare a method first and then declare what it does later outside of class definition. It works like a place keeper before you actually define what it is you want that method to do. It makes the code a lot cleaner.... i dunno if you wanna sample or something.

Link to comment
Share on other sites

I am fully cognizant of that, but I am commenting on the fact that he declares the same variable twice in his code. Once globally and once locally.

 

 

public class DoesntWork{
int x; // This is a Variable Declaration in Java.
int x; //Compile time error: x is already defined in Doesntwork
}

 

public class DoesntWorkAlso{
Object x;

public DoesntWorkAlso(){
	Object x = new Object(); //Compiles with no errors. I believe it overrides the global declaration of the variable. I expect a runtime error, but one would need to read the API and perform tests to be sure. 
}
}

 

public class DoesWork{
Object x; //Declare variable x of Type Object
public DoesWork(){
	x /*This is a Variable Reference in Java.*/ = new Object(); //Reference variable x and assign it to a new Instance of Object via the default Object Constructor.
}
}

 

There could be something going on which I am unfamiliar with, as always. I wrote a piece of code which in my best estimation shouldn't work, but evidentially does. I'll scan the rest of the code to see if I can find any other oddities.

Link to comment
Share on other sites

//initializer
   public void SetPosition(int a, int b, int c)
   {
       LeftX = a;
       RightX = b;
       MaxY = c;
               
       XBrick = (RightX - LeftX) / Globals.BLOCK_WIDTH;
       YBrick = MaxY / Globals.BLOCK_HEIGHT;
       
       BuildingBlock bricks[][] = new BuildingBlock[XBrick][YBrick]; //Locally declared override of bricks. Method calls to the variable bricks' elements should only be valid to the scope of this method and it's sub calls.
       
       //instantiate all bricks
       for(int x = 0; x < XBrick; x++)
       {
           for(int y = 0; y <= YBrick - 1; y++)
           {
               bricks[x][y] = new BuildingBlock();
               bricks[x][y].SetPosition(x * Globals.BLOCK_WIDTH, y * Globals.BLOCK_HEIGHT);
           }
       }
       //make sure all bricks are intact
       for(int h = 0; h < XBrick; h++)
       {
           for(int v = YBrick - 1; v >= 0; v--)
           {
               try 
               {
                   bricks[h][v].Intact();                    
               } 
               catch (NullPointerException e) 
               {
                   System.out.println("H:" + h + " V:" + v);
                   System.out.println("XBrick:" + XBrick + " YBrick:" + YBrick);
               }
           }
       }
//Sure enough we exit the scope of this method without assigning our double array to a globally scoped variable. 
//First call to the array's elements outside this method should return a NullPointerException.
   }

Link to comment
Share on other sites

Alex, your note listening/reading. :)

 

I have no problem with the constructor. I have no problem with the assignment. My issue lies in the declaration override of the variable bricks[][] which redefines the scope of bricks to the method rather than globally to the rest of the object. The result is that the moment the object calls on an array index of bricks outside of the SetPosition() method, it will fail throwing a NullPointerException. if you read my comments at the bottom of the previously posted code, I explain what is happening. I tested it myself to triple check my work.

 

The issue is the variable SetPosition()::bricks[][] goes out of scope once Dave leaves the method. He is, in fact, instantiating the elements of bricks, but when he's done with SetPosition(), the instance of bricks used by SetPosition() is marked for garbage collection as it passes out of scope. Globally speaking, he hasn't instanced bricks in the object. The proof comes when he calls on the objects which don't exist in memory, of course. His indexes, h and v, are checked and are fine in the Collision method, but bricks in the scope of the same method is null.

 

If I had the pieces the code depended upon, I could fix the code, compile, test, and post it to prove the point.

 

The issue stems from him declaring bricks globally(BuildingBlocks::bricks[][]), overriding bricks locally(BuildingBlocks::SetPosition()::bricks[][]). It may be standard and permissible without compiler error. The ability to override the scope of a variable might even be desirable in some cases. It maybe a standard feature of OOP languages, but in this case it is a bug rather than a feature.

 

If he removed the second declaration as I have suggested multiple times now, it would resolve the issue. You can check this by writing a brief Object Array class with a init() function and another function which attempts to access the array elements.

 

TL;DR: Inside SetPosition, the bricks are allocated, assigned, and perfectly formed. The bricks are unreachable from outside SetPosition().

Link to comment
Share on other sites

oh i got you, you just didnt post all of the code you were referring to... looking back at the original code i see what you meant

 

It's not that you cant declare a variable of that type within the method, you can, and the code is leggit, problem is you are not instantiating the one you declared in your private, you instantiate a variable that you declared in that method... and they are not the same.

 

brick gets declared locally, it doesnt override the previous declaration, but it creates a variable in the scope of the method, and you are 100% right, if he were to instantiate the class member, not a variable within the function, the problem would not exist...

 

illustration :)

 

public class brick
{

private int a, b, c;

//standard constructor
public brick()
{
a=0;
b=0;
c=0;
}

//note this is overloaded constructor that instantiates 3 local variables that have the same names as private class variables, and we are accessing both the local a,b,c and class a,b,c...

public brick(int a, int b, int c)
{
//a in here is different from the private declaration 
this.a = a;
this.b = b;
this.c = c;
}

}

 

and all of it can be traced with a little debugging ;)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...