Let me see if I can shed some light on the subject.
When thinking about recursion, it helps (me at least), to think about the program in a more declarative way, meaning, you think about what you're trying to accomplish, instead of thinking about each step of the algorithm needed to accomplish it.
Let's check your example, you need to find the max value in an Array, so we'll break down this problem in smaller problems.
If the size of the Array is 1, there's only one element... so that one is the maximum. Easy.
The problem of finding the max can be described as: The greater value between one element of the list, and the maximum of all the other elements.
That's what you're doing in the rest of the code. You apply the algorithm to the array from the position 0 to length-1, and then compare the returning value.
These calls will create a Recursion Tree, meaning, there will be several calls "nested", until each call is done with length=1 (the base case), and then, the algorithm will start reconstructing the answer.
The best way of really understanding a recursive algorithm is to grab a piece of paper and emulate the program, write the values of your array and the value of "length" on the paper for each call, and then figure out what happens after each call finally reaches a base case.
For {1,1,0,2}, you'll basically get a chain of calls, something like:
max(maxFind({1,1,0}), 2)
Where maxFind({1,1,0}) boils down to:
max(maxFind({1,1}), 0)
and maxFind({1,1}) is
max(1,1) = 1
Then this starts boiling up (it's the reverse order from above):
max(1, 0) = 0
max(1, 2) = 2
So the result will be 2.