Null Pointer Exception on Object Array

Hey you guys,
I hope you can help me with this. I am creating a little game, for which I need an array of Snowflakes (an object I created), which I create and instantiate. Despite that I am still getting a NPE. Here’s my code:
Main Class:

//Global vars
Panel panel;
Snowflake[] flakes;

void setup() {
    fullScreen(P2D);
    panel = new Panel();
    flakes = new Snowflake[5];
    for(Snowflake sf:flakes){
        sf = new Snowflake(int(random(20, width - 20)), int(random(20, height - 20)), 20, 3);
        sf.drawSnowflake();
    }

}

void draw() {
    background(0);
    panel.drawPanel();
    for(Snowflake sf:flakes){
        sf.drawSnowflake();
    }
    
}

Snowflake Class:

class Snowflake{

    int posX;
    int posY;
    int offset;
    int speed;
    boolean firstDraw = true;

    public Snowflake(int posX, int posY, int offset, int speed){
        this.posX = posX;
        this.posY = posY;
        this.offset = offset;
        this.speed = speed;
    }

    public void drawSnowflake(){
        if(firstDraw == true){
            createSFShape(posX,posY,offset);
            firstDraw = false;
        }
        else{
            int rPosY;
            if(posY >= height){
                rPosY = 0;
                posY = rPosY;
            }
            else{
                rPosY = posY + speed;
                posY = rPosY;
            }
            createSFShape(posX,rPosY,offset);
        }
    }

    public void createSFShape(int x, int y, int offset){
        stroke(255);
        line(x, y - offset, x, y + offset);
        line(x - offset, y, x + offset, y);
        line(x - offset, y - offset, x + offset, y + offset);
        line(x + offset, y - offset, x - offset, y + offset);
        
    }
}

I hope you can help me with this and thanks for reading!

PS: If I create a single Snowflake, the code works.

1 Like

Forgot to add the stacktrace, here it is:

NullPointerException
Could not run the sketch (Target VM failed to initialize).
For more information, read revisions.txt and Help ? Troubleshooting.

Processing highlights the line

 sf.drawSnowflake();
1 Like

You can’t populate an array with for-each loop

for(int i = 0; i < flakes.length; i++){
        flakes[i] = new Snowflake(int(random(20, width - 20)), int(random(20, height - 20)), 20, 3);
        flakes[i].drawSnowflake();
    }
2 Likes

Or

for(int i = 0; i < flakes.length; i++){
        flakes[i] = new Snowflake(int(random(20, width - 20)), int(random(20, height - 20)), 20, 3);
    }
for(Snowflake sf:flakes){
        sf.drawSnowflake();
    }
1 Like

Ok, that fixed it. Why can’t you use a for-each loop, if you don’t mind me asking?

Because in the for-each loop the variable sf is a local variable which is a copy of the reference in the array. You can alter it but it doesn’t alter the array or collection it comes from.

1 Like
  • B/c its iterator variable is local to the loop.
  • On each iteration the iterator is assigned w/ 1 of the array’s indices.
  • Assigning something else to the iterator won’t affect the array’s content.
  • Here’s an example similar to what happens to an enhanced loop iteration:
final PVector[] vecs = new PVector[5]; // 5 indices (0 to 4)
println(vecs); // starts off all null

PVector vec = vecs[0]; // local variable vec equals to null
vec = PVector.random3D(this); // reassigning w/ another value won't affect vecs[0]
println(vecs[0]); // vecs[0] is still null

vecs[0] = PVector.random3D(this); // direct assignement to index 0
println(vecs[0]); // now vecs[0] is initialized w/ a PVector object

exit();
2 Likes