Inside, I believe that most Java list objects actually have at some point an immutable array, and that is what you are using.
What they do to resize, at the threshold of %% (say 75%), they will create a new array with doubled size. Therefore, if you have an array of 4 elements and three elements are inserted, the structure will internally update its storage array to size 8 and do it again when there were 6 elements, etc.
For the actual copy, look at System.arraycopy, which allows you to specify your source and target array.
As for the shift, why shift? Why not just keep a pointer to the current index?
For example, look at this chain of operations ...
Queue object, Queue object, Deactivation object, Queue object.
Your structure may look like
[,,,] - head at 0, tail at 0 [obj1,,,] - head at 0, tail at 1 [obj1,obj2,,] - head at 0, tail at 1 [obj1,obj2,,] - head at 1, tail at 1 [obj1,obj2,obj3,] - head at 1, tail at 2 [obj1,obj2,obj3,] - head at 2, tail at 2
Using this method and, as described in other answers, you can also wrap your indexes on elements that are still available. In the above example, if you added two more elements since the first two are no longer in use, you can start replacing them with new elements.
Obviously, you still have to handle resizing when enough objects are not allocated to allow more queuing.