Let's start from the beginning:
You probably already know that a recursive function is one that calls itself. If every time a function runs it calls itself, you are going to end up in an infinite loop. Therefore, it is important to always make sure your function knows when to stop calling itself as well.
How can we do this? The body of the function is not going to change between calls, since it is set at compile time. What will change, however, is the input to the function. Whenever you write a recursive function, you need to include logic that will avoid the recursive call when a certain condition is met.
In your example, the input to your function is an array of Strings. One way to know when to stop making the recursive call could be to pass a smaller array to the function each time, and stop when you have an empty array. This would work better in a language like C where arrays are exposed as pointers, but in Java it would be inefficient as you would have to create a new array each time.
A nicer solution would be to maintain an index pointing to your current position in the list (this is why you need a helper function - to add the extra parameter). At each call, you can simply print the String at the current index and increment the index. When the index is no longer inside the array, you're done!
If you really want to get a good understanding of recursion, I recommend learning a functional language such as Lisp, Haskell, or ML. Functional languages avoid mutable state (changing the values of variables), and as such they don't use things like for loops (because of the need to update a loop counter at every iteration). So they implement loops using recursion instead! For example, in Java we might have:
for (int i = 0; i < 10; i++) {
System.out.println("Loop index: " + i);
}
whereas in OCaml we would write the following:
let times = 10 in
let rec loop count =
if count = times then
printf "Loop index: %d" count ;
loop (count + 1)
;;
The important difference here is that, rather than changing the value of count (actually not possible given the above OCaml code), we pass a new value into the loop
function each time.