pgrmdave Posted April 11, 2007 Report Posted April 11, 2007 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() Quote
alexander Posted April 11, 2007 Report Posted April 11, 2007 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) Quote
Buffy Posted April 11, 2007 Report Posted April 11, 2007 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! Hope this helps! Keep asking questions! Watching variables,Buffy Quote
pgrmdave Posted April 13, 2007 Author Report Posted April 13, 2007 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; } } Quote
alexander Posted April 16, 2007 Report Posted April 16, 2007 netbeans debug tutorial debugger = friend :D i hope that helps a little Quote
IDMclean Posted December 17, 2008 Report Posted December 17, 2008 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]; Quote
alexander Posted December 17, 2008 Report Posted December 17, 2008 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. Quote
IDMclean Posted December 19, 2008 Report Posted December 19, 2008 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. Quote
IDMclean Posted December 19, 2008 Report Posted December 19, 2008 //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. } Quote
alexander Posted December 19, 2008 Report Posted December 19, 2008 that part is fine, its the constructor method, it gets executed when you instantiate the class, in our case it will set all the variables (members) to their initial vals. Its a standard thing in OO language as well. Quote
IDMclean Posted December 23, 2008 Report Posted December 23, 2008 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(). Quote
alexander Posted December 23, 2008 Report Posted December 23, 2008 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 ;) Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.