The "UTF-8 by Default" refers to the default character set used for decoding and encoding, when Java Strings are read and written. Prior to JEP 400, the default character set was "platform specific." It was often UTF-8, but sometimes it was not, in which case hijinks ensued.
As noted elsewhere the internal representation of Java Strings is either UTF-16-like or is Latin-1, if all the characters of the String can be encoded in Latin-1. We think about using UTF-8 as an internal representation constantly. Doing so would potentially save space and reduce decoding/encoding overhead.
Unfortunately doing this is difficult. The key issue is that tons of code out there treats a String as a UTF-16 array (since that's what's in the API) so there are coding patterns like this:
for (int i = start; i < end; i++) {
char ch = str.charAt(i);
// do something with ch
}
If the internal representation were UTF-8, simplistically, `charAt(i)` would change from O(1) to O(N). Of course there are cleverer things one could do, such as converting to UTF-16 lazily. Now `charAt()` allocates memory and has variable latency. Well then partial conversion could be done and the current iteration point could be cached. This might work, but now String has state, and it's thread-specific as well. Etc.