пятница, 10 июля 2015 г.

Интернирование строк

Как известно, java хранит строки в некотором кэше находящимся в памяти. Это называется интернирование. В целях экономии памяти все одинаковые строки встречающиеся в коде, ссылаются на один и тот же объект. Следующий код не всегда может выводить true

        String firstString="hi";
        //other code
        String secondString = new String("h")+"i";
        System.out.println(firstString.equals(secondString));
Первая строка известна компилятору, вторая - создается в runtime, и компилятор не смог провести оптимизацию, сделав так, чтобы обе строки ссылались на один и тот же объект. Следовательно, все последующие строки встречающиеся в коде с содержимым "hi", созданные через new либо явно заданные, будут ссылаться на один объект, что и первая строка. Немного поизвращаемся и изменем объект на который ссылается первая строка.
        Field field = firstString.getClass().getDeclaredField("value");
        field.setAccessible(true);

        Field modifiers = Field.class.getDeclaredField("modifiers");
        modifiers.setAccessible(true);
        modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(firstString, "bye".toCharArray());
Теперь все строки "hi" на самом деле ссылаются на строку с содержимым "bye" ;)