ok, hab mal nachgesehen, was bei .substring passiert:
GrepCode: java.lang.String (.java) - Class - Source Code View
http://grepcode.com/file/repository.grepcode.com/java/root/
jdk/openjdk/6-b14/java/lang/String.java#String.%3Cinit%3E%28int%2Cint%2Cchar[]%29
Es wird ein package private constructor aufgerufen, der mit demselben char[] (Referenz wird kopiert) ein neues String-Objekt erstellt/instantiiert. Das geht ja, weil sich das char[] nicht ändern darf.
Es werden also keine Zeichen kopiert. Damit sollte .substring schneller sein, als ein neues char[] zu erstellen