Java - скажите, интернирована ли строка? - PullRequest
14 голосов
/ 03 февраля 2011

Итак, вопрос здесь довольно прост: есть ли способ определить, является ли String в Java интернированным? Я думаю, нет, но мне интересно, если кто-нибудь знает лучше.

Ответы [ 4 ]

15 голосов
/ 03 февраля 2011

Единственный способ узнать, интернирован ли String, - это позвонить intern() и проверить, возвращается ли он сам:

boolean hasBeenInternedBefore = myString.intern() == myString;

Очевидно, что этот недостаток заключается в интернировании String, когда он не был интернирован ранее.

Частично не по теме, есть способ сделать "настраиваемое" интернирование с явным пулом, используя Interner интерфейс из Гуава (используя реализации, представленные Interners класс ). Это дает преимущество, заключающееся в том, что можно самому Interner (и использовать пул) собирать мусор, когда на него больше нет ссылок.

2 голосов
/ 25 июля 2015

Существует способ проверить, был ли конкретный объект String уже интернирован, но он вставляет содержимое в пул строк, если оно еще не было интернировано.Создайте новый String объект с тем же содержимым, интернируйте его и сравните с исходным объектом:

new String(s).intern() == s

Это работает из-за того, что new String(s) != s.Рассмотрим каждую возможную ситуацию:

  1. s интернирован в пул строк.new String(s) имеет то же содержимое, что и s, поэтому вызываемый intern() вернет s.Результат выражения: true.
  2. s не интернирован в пуле строк, но другой равный String объект - давайте назовем его s2.intern() вернет s2, поэтому результат выражения будет false.
  3. s не интернирован в пул строк, и ни один из них не равен String.В этом случае new String(s) будет встроен в пул строк, который, к сожалению, изменяет пул строк.Поскольку это не тот же объект String, что и s, результатом выражения будет false.

Таким образом, приведенное выше выражение будет правильно проверять, интернировано ли s в пуле строкне.Следующий тест демонстрирует это:

public static void main(String[] args) {
    String interned = new String(new char[] { 'i', 'n', 't' }).intern();
    String notInterned = new String(new char[] { 'n', 'o', 't' });
    System.out.println("Case 1: " + wasInterned(interned));
    System.out.println("Case 2: " + wasInterned(new String(interned)));
    System.out.println("Case 3: " + wasInterned(notInterned));
}

public static boolean wasInterned(String s) {
    return new String(s).intern() == s;
}

При запуске вывод:

 Case 1: true
 Case 2: false
 Case 3: false
0 голосов
/ 03 февраля 2011

Нет. Вообще говоря, вам не нужно проверять - просто intern, чтобы быть уверенными или не полагаться на интернирование Если вам нужны интернированные или не интернированные строки для тестирования или эксперимента, вы можете сделать их:

интернирован:

s = someArbitraryString.intern();

Non-интернирован:

s = new String(someArbitraryString);
0 голосов
/ 03 февраля 2011

Мы не можем заглянуть внутрь репозитория внутренних строк и не можем получить набор всех внутренних строк.

Тестирование, если данная строка была интернирована, уже создает хорошую дилемму (кстати, распространенная проблема с измерениями): само измерение может повлиять на хранилище интернированных строк;)

Toпроверить, если хранилище содержит данную строку, нам нужно сравнить эту строку со всеми строками в этом хранилище (наихудший случай) - с риском того, что JVM интернирует эту ссылочную строку до того, как мы начнем сравнивать ...который вернул бы true, хотя строка не была интернирована перед тестом;)

Но кроме этого, я не вижу никакого практического применения в том, чтобы узнать, интернирована ли уже виртуальная машина в строке илине.Стажировка достаточно дешевая, просто стажируйте ее, если это необходимо.(И если бы было практическое применение, класс String предложил бы собственный метод тестирования)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...