Ve včerejším článku zmínil Karel Čížek velmi zajímavou věc, která zůstala v diskuzi pod ním nepovšimnuta. Od některé velmi nedávné verze JDK (v 1.7 u11 už tomu tak je) jsou ze Stringu odstraněny intové fieldy count a offset a zůstává tak pouze char[] value (+ cachovaný hashcode). To má za následek jednak zmenšení stringů o 8 bajtů a jednak přestává platit zmiňované sdílení char polí při použití metody substring():
public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }
Poslední řádka zde volá standardní veřejný konstruktor, který char pole kopíruje. Package-private String(int, int, char[]) byl označen jako deprecated (v JDK 8 je už odstraněn úplně) a metody jako concat, replace atd. byly upraveny tak, že nyní používají nový neveřejný konstruktor, který sice char pole také nekopíruje, nicméně je mu vždy předáváno pole nově vytvořené.
/* * Package private constructor which shares value array for speed. * this constructor is always expected to be called with share==true. * a separate constructor is needed because we already have a public * String(char[]) constructor that makes a copy of the given char[]. */ String(char[] value, boolean share) { // assert share : "unshared not supported"; this.value = value; }
Je to tak a (z trosku jinych duvodu, nez kvuli clankum na rootu) projedu benchmarky, kde se ukaze, jak se tato uprava projevi. Podle me bylo puvodni chovani klasicka preliminary optimalization s dobrym umyslem, ale nikoho v te dobe nenapadlo, ze Java se bude velmi casto pouzivat na drceni textovych dat (XML), kde to zachovani puvodniho retezce je na skodu.