In this case details of implementation of methods charAt and substring are helpful to know.
charAt as described in this tutorial can be described as method that:
returns the character located at the String's specified index. The string indexes start from zero.
That is why calling:
System.out.println("hello".charAt(5));
gives
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 5
Because maximum index is, as you perfectly described, only 4.
substring
is described in java documentation and explains your exact situation here in the "Examples" section which states that :
"emptiness".substring(9) returns "" (an empty string)
For additional reference, here is the source code for java's substring(int index) implementation, where you can see that it uses java's substring(int beginInndex, int endIndex)
method.