Why am I getting a NullPointerException on this object?

1353 views java
2

I have an object of type PolyaUrn called myUrn. I instantiate it and use some methods to manipulate it. Then, I get the int[] field of myUrn named ballCounts. I pass this int[] to a constructor to create a new object of type SimpleUrn, named su. However, when I try to call methods on su I get a NullPointerException. I am using the new keyword to create an object of type SimpleUrn and point to variable su. I don't understand why I can't reference su using the dereferencing operator .

Code below:

import java.util.Arrays;

class PolyaUrnProg {

  public static void main(String[] args) {
    PolyaUrn myUrn = new PolyaUrn();
    myUrn.draw();
    myUrn.draw();
    System.out.println(myUrn);
    System.out.println();

    int numDraws = 100; // we will make another 98 draws from the urn

    for (int i = 0 ; i < numDraws-2 ; i++) {
      myUrn.draw();
    }
    System.out.println("...and after 98 more draws:\n");
    System.out.println(myUrn);

    System.out.println('\n');
    System.out.println("Let's construct a SimpleUrn from original PolyaUrn.");

    // initialising new int array with the same size as myUrn
    int[] a = new int[myUrn.getArray().length];

    // copying myUrn into 'a'
    a = Arrays.copyOf(myUrn.getArray(), myUrn.getArray().length);

    // passing 'a' to constructor in SimpleUrn to initialize it
    SimpleUrn su = new SimpleUrn(a);

    //ERROR - NullPointException
    su.toString();
  }
}

PolyaUrn class:

import java.util.Arrays;

class PolyaUrn {

  private int[] ballCounts;
  private int lastDraw;

  public PolyaUrn() { // Sets up PolyaUrn by rolling it

    ballCounts = new int[2]; // initially two possibilities
    ballCounts[0] = 1;
    ballCounts[1] = 1;

    // last draw is not a meaningful value until a ball is drawn.
    lastDraw = -1;
  }

  public int[] getArray() {
    return ballCounts;
  }

  public int getLastDraw() {
    return lastDraw;
  }

  public int[] updateUrn(int b) {

    if(b == 0) {

      int[] newUrn = Arrays.copyOf(ballCounts, ballCounts.length+1);
      newUrn[newUrn.length-1] = 1;
      ballCounts = newUrn;

    } else {

      ballCounts[b] = ballCounts[b]+1;
    }

    return ballCounts;
  }

  public void draw() {
    int ballDrawn = WeightedSampler.sample(ballCounts);
    updateUrn(ballDrawn);
    lastDraw = ballDrawn;
  }

  public String toString() {
    String s = "Polya Urn\n=========\n\n";
    s += "Ball-counts are as follows:\n\n";
    s += " Value\t| Count\n";
    s += "----------------\n";
    for (int ballValue = 0; ballValue < ballCounts.length ; ballValue++) {
      s += "  " + ballValue + "\t|  " + ballCounts[ballValue] + "\n";
    }
    return s;
  }
}

SimpleUrn class:

import java.util.Arrays;

class SimpleUrn {

  private int[] ballCounts;
  private int lastDraw;

  public SimpleUrn(int[] ballArray) { // Sets up PolyaUrn by rolling it

    int[] ballCounts = ballArray;

    // last draw is not a meaningful value until a ball is drawn.
    lastDraw = -1;
  }

  public int getLastDraw() {
    return lastDraw;
  }

  public int[] updateUrn(int b) {

    ballCounts[b] = ballCounts[b]-1;
    return ballCounts;
  }

  public void draw() {

    int ballDrawn = WeightedSampler.sample(ballCounts);
    updateUrn(ballDrawn);
    lastDraw = ballDrawn;
  }

  public String toString() {
    String s = "Polya Urn\n=========\n\n";
    s += "Ball-counts are as follows:\n\n";
    s += " Value\t| Count\n";
    s += "----------------\n";
    for (int ballValue = 0; ballValue < ballCounts.length ; ballValue++) {
      s += "  " + ballValue + "\t|  " + ballCounts[ballValue] + "\n";
    }
    return s;
  }
}

Note: these classes use a 3rd class, WeightedSampler, incase someone wants to compile. This class is here:

import java.util.Random;
import java.util.stream.*;

public class WeightedSampler {

  private static Random generator = new Random(); 

  public static int sample(int[] weights) {
    int total = calculateSum(weights);
    int remains = generator.nextInt(total);
    int index = 0;

    while (index < weights.length) {
      remains -= weights[index];
      if (remains < 0) {
        break;
      }
      index++;
    }
    return index;
  }

  public static int calculateSum(int[] arr){
    return IntStream.of(arr).sum();
  }
}

answered question

Next time you ask a question about an exception, always post the exact a complete stack trace of the exception. It tells precisely where the exception happens.

@JB. Not next time

1 Answer

4

You are shadowing ballCounts in the SimpleUrn constructor. Change this

public SimpleUrn(int[] ballArray) { // Sets up PolyaUrn by rolling it
    int[] ballCounts = ballArray;

    // last draw is not a meaningful value until a ball is drawn.
    lastDraw = -1;
}

To

public SimpleUrn(int[] ballArray) { // Sets up PolyaUrn by rolling it
    this.ballCounts = ballArray;

    // last draw is not a meaningful value until a ball is drawn.
    lastDraw = -1;
}

posted this

Have an answer?

JD

Please login first before posting an answer.