8

When I try to push an element into a Java array where I take the array size from a constructor argument, it throws an ArrayIndexOutOfBoundsException exception. However, when I set the size while declaring the array adding an element works.

Here is my code:

public class Stack {
    public int size;

    public Stack(int size)
    {
        this.size = size;
    }

    public int[] arr = new int[size];

    public int top = -1;

    // Methods
    public void push(int value)
    {
        top++;
        arr[top] = value;
    }
}

The following throws the exception:

new Stack(10).push(123);
Rodrigue
  • 3,617
  • 2
  • 37
  • 49
A.Usama
  • 157
  • 2
  • 8
  • 1
    Possible duplicate of [Default constructor vs. inline field initialization](https://stackoverflow.com/questions/4916735/default-constructor-vs-inline-field-initialization) – Logan Jul 23 '18 at 20:17
  • You need to put this line into constructor's body: `arr = new int[size]; ` – Ivan Jul 23 '18 at 20:20
  • When an instance of `Stack`i is created the member variable `size` is initialized by default with the value `0` and in consequence the array `arr` is initialized with `size == 0`. When calling `push` the first time there is the attempt to set element `0` of `arr`. But `arr`has no elements as it's size is `0`. – LuCio Jul 23 '18 at 20:31
  • @Ivan yeah it works ty but can you explain why we need to do that ? – A.Usama Jul 23 '18 at 20:31
  • Ahmed Usama, @LuCio is completely right, see [**my answer**](https://stackoverflow.com/questions/51486618/out-of-bounds-exception-in-while-stack-pushing/51486815#51486815) about it in order to see a detailed explanation (pay attention to the comments in the code) – lealceldeiro Jul 23 '18 at 20:43

1 Answers1

7

You need to initialize the array when the value of this.size is the "correct" one. Initially the value of this.size is 0 (zero) (see Initial Values of Variables) so this is not the time of initializing the array; you must "wait" in order to know what's the size the array will have. Where that size is provided? In the class constructor.

So it is inside the constructor where you have to initialize the array (with the provided size).

For example, see below commented code (yours):

public class Stack {
    public int size ;                   // size = 0 at this time
    public Stack(int size)
    {
        this.size = size;
    }
    public int[] arr = new int[size];  // still size = 0 at this time!
                                       // so you're creating an array of size zero
                                       // (you won't be able to "put" any value in it)
    public int top = -1;

    //Methods
    public void push(int value)
    {
        top++;             // after this line `top` is 0
        arr[top] = value;  // in an array of zero size you are trying to set in its
                           // "zero" position the value of `value`
                           // it's something like this:
                           // imagine this array (with no more room)[], can you put values?,
                           // of course not
    }
}

So, in order to fix this you need to change your code like this:

public class Stack {

    public int size;
    public int[] arr;         // declare the array variable, but do not initialize it yet
    public int top = -1;

    public Stack(int size) {
        this.size = size;
        arr = new int[size];  // when we know in advance which will be the size of the array,
                              // then initialize it with that size
    }

    //Methods
    public void push(int value) {
        top++;
        arr[top] = value;
    }
}
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • In this Block , how size still 0 and i just take the value from main ? public Stack(int size) { this.size = size; //the value must be taken and assigned to size } public int[] arr = new int[size]; //How still 0 here – A.Usama Jul 23 '18 at 20:46
  • Further reading: [specification of default values in the JLS](https://docs.oracle.com/javase/specs/jls/se10/html/jls-4.html#jls-4.12.5) – LuCio Jul 23 '18 at 20:48
  • Thanks @LuCio!, can I add that info to the answer? – lealceldeiro Jul 23 '18 at 20:49
  • 1
    Sure. Go ahead! – LuCio Jul 23 '18 at 20:50
  • @AhmedUsama in your initial code `size` has a default value (see LuCio link), so if you don't initialize the array inside the controller with the size provided as parameter the array length will be that default (initial) value – lealceldeiro Jul 23 '18 at 20:51
  • @AhmedUsama see my answer updated. I hope it is clearer now – lealceldeiro Jul 23 '18 at 20:56