0

I'm stuck on something that is usually really simple. I'm getting a NullPointerException when calling this simple class's constructor:

import java.awt.geom.*;

public class Brick extends ColorShape {
        private int xPos = 0;
        private int yPos = 0;
        private int width = 0;
        private int height = 0;
        private Rectangle2D.Double shape;

        // constructor
        public Brick(int x, int y, int w, int h) {
            super(new Rectangle2D.Double(x, y, w, h));

            //set brick x, y, width, and height
            xPos = x;
            yPos = y;
            width = w;
            height = h;

            // update shape
            shape.setRect((double)xPos, (double)yPos, (double)width, (double)height);
        }

        public int getX() {
            return xPos;
        }

        public Rectangle2D.Double getShape() {
            return shape;
        }
    }

It gets called this way:

for (int i = 0; i < numCols; i++) {
            for (int j = 0; j < numRows; j++) {

                // initialize bricks[i][j]
                bricks[i][j].setLocation((double)(i*brickWidth), (double)(j*brickHeight));
                bricks[i][j].setSize((double)brickWidth, (double)brickHeight);
                //bricks[i][j] = new Brick(i*brickWidth, j*brickHeight, brickWidth, brickHeight);
                //bricks[i][j] = new Brick(0, 0, 0, 0);
            }
        }

No matter what I try, I always get a NullPointerException trying to initialize that class.

EDIT:

Tristan's suggestions along with changing the nested for loops to the code below fixed it

// create new bricks and store them in bricks array
        for (int i = 0; i < numCols; i++) {
            for (int j = 0; j < numRows; j++) {


                // initialize bricks[i][j]
                //bricks[i][j].setLocation((double)(i*brickWidth), (double)(j*brickHeight));
                //bricks[i][j].setSize((double)brickWidth, (double)brickHeight);
                bricks[i][j] = new Brick(i*brickWidth, j*brickHeight, brickWidth, brickHeight);
                //bricks[i][j] = new Brick(0, 0, 0, 0);
            }
        }
user3161533
  • 427
  • 1
  • 4
  • 6

2 Answers2

2

I think you are accidentally redeclaring shape as an uninitialized field. The shape you are calling setRect on has not been initialized the way you think it has.

If you have a shape in the parent class that you are trying to access, simply set its modifier to protected and remove the private shape declaration in the class you posted.

/* REMOVE THIS */
private Rectangle2D.Double shape; // uninitialized!

// constructor
public Brick(int x, int y, int w, int h) {
    super(new Rectangle2D.Double(x, y, w, h));

    //set brick x, y, width, and height
    xPos = x;
    yPos = y;
    width = w;
    height = h;
    // update shape
    // This now references a protected instance variable inherited from the parent.
    shape.setRect((double)xPos, (double)yPos, (double)width, (double)height);
}

However looking through this constructor, it seems rather off. If it is the case that the parent class has a shape itself, why do you need to set the rectangle any differently than the way you set it in the parent class?

For example, this code appears to be logically equivalent.

// Call the parents constructor to set the shape of this brick..
public Brick(int x, int y, int w, int h) {
    super(new Rectangle2D.Double(x, y, w, h));
}
Tristan
  • 2,349
  • 16
  • 11
  • ok. Just to test it, i changed it to this private Rectangle2D.Double shape = new Rectangle2D.Double(0,0,1,1); and still have the same error – user3161533 Mar 15 '14 at 01:14
  • Don't change it to private, just remove it. Does your parent class have an instance variable named shape? – Tristan Mar 15 '14 at 01:18
  • the code won't execute anything past super(new Rectangle2D.Double(x, y, w, h)); in the constructor. supre refers to ColorShape.ColorShape(RectangularShape s) – user3161533 Mar 15 '14 at 01:18
  • Maybe there's a good reason for holding onto `int` versions of the dimensions. It looks like otherwise he'd have to cast `double`s back to `int`s. Although it would probably take a really big loop before this caused any noticeable performance problems. – ajb Mar 15 '14 at 01:18
  • It's possible. Not sure if thats what he is trying to do though :P – Tristan Mar 15 '14 at 01:20
  • i removed it like you asked. afterwards it complaine that setRect didn't exist so I found something similar // update shape shape.setFrame((double)xPos, (double)yPos, (double)width, (double)height); but it still throws the same error – user3161533 Mar 15 '14 at 01:21
  • @user3161533 So far, you haven't told us what line it's getting the `NullPointerException` on. (I'm not even certain that it's been on the same line every time you've tried it.) Did you look at the stack trace and find out? – ajb Mar 15 '14 at 01:24
  • I removed everything in the constructor but super(new Rectangle2D.Double(x, y, w, h)); The line: super(new Rectangle2D.Double(x, y, w, h)); will not execute and is throwing the exception. – user3161533 Mar 15 '14 at 01:25
  • Did you set the parent class modifier of shape to protected? – Tristan Mar 15 '14 at 01:26
  • I can't access it. I did get the code to work though. I'll edit the post and mark this answer as soon as I finish editing. – user3161533 Mar 15 '14 at 01:29
0

As mentioned by Tristan, the problem with the initial brick constructor is that shape has been declared but not instantiated.

That said, it is simple to instantiate shape:

public Brick(int x, int y, int w, int h) {
    super(new Rectangle2D.Double(x, y, w, h));

    //set brick x, y, width, and height
    xPos = x;
    yPos = y;
    width = w;
    height = h;
    // update shape
    // This now references a protected instance variable inherited from the parent.
    shape = (Rectangle2D.Double)super.shape;
    shape.setRect(xPos, yPos, width, height);
}
Brett Nelson
  • 83
  • 2
  • 8