Как пул строк реализован в java? [Дубликат]

Самое простое решение - создать функцию JavaScript и вызвать его для обратного вызова Ajax success.

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);    
}); 
151
задан nbro 25 February 2015 в 23:13
поделиться

9 ответов

new String("text"); явно создает новый и ссылочно выделенный экземпляр объекта String; String s = "text"; может повторно использовать экземпляр из пула строковых констант, если он доступен.

Вы очень редко хотели бы использовать конструктор new String(anotherString). Из API:

String(String original) : Инициализирует вновь созданный объект String, чтобы он представлял ту же последовательность символов, что и Аргумент; Другими словами, вновь созданная строка является копией строки аргумента. Если явная копия оригинала не нужна, использование этого конструктора необязательно, поскольку строки неизменяемы.

Связанные вопросы


Что означает референциальное различие

Изучите следующий фрагмент:

    String s1 = "foobar";
    String s2 = "foobar";

    System.out.println(s1 == s2);      // true

    s2 = new String("foobar");
    System.out.println(s1 == s2);      // false
    System.out.println(s1.equals(s2)); // true

== по двум ссылкам типы - это сравнение ссылочной идентичности. Два объекта equals не обязательно ==. Обычно неверно использовать == для ссылочных типов; большую часть времени equals нужно использовать вместо этого.

Тем не менее, если по какой-то причине вам нужно создать две строки equals, но не ==, вы можете используйте конструктор new String(anotherString). Однако необходимо повторить, что это очень своеобразно и редко является намерением.

Ссылки

Связанные с этим вопросы

153
ответ дан Community 25 August 2018 в 16:20
поделиться

Строковые литералы войдут в String Constant Pool.

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

enter image description here [/g3]


Создание объектов по строкам:

String str1 = new String("java5");

Используя строковый литерал «java5» в конструкторе, новое строковое значение сохраняется в пуле строковых констант. Используя новый оператор, в куче создается новый строковый объект с «java5» в качестве значения.

String str2 = "java5"

Ссылка «str2» указана на уже сохраненное значение в пуле константных строк

String str3 = new String(str2);

В куче создается новый строковый объект с тем же значением, что и ссылка на «str2»

String str4 = "java5";

Ссылка «str4» указана на уже сохраненное значение в пуле константных строк

Всего объектов: куча - 2, пул - 1

Дальнейшее чтение сообщества Oracle

97
ответ дан Lucky 25 August 2018 в 16:20
поделиться

Один создает String в String Constant Pool

String s = "text";

, другой создает строку в пуле констант ("text") и другую строку в обычной куче пространство (s). Обе строки будут иметь то же значение, что и «текст».

String s = new String("text");

s затем теряется (подходит для GC), если позже не используется.

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

14
ответ дан user 25 August 2018 в 16:20
поделиться

Подумайте, что "bla" является волшебной фабрикой, например Strings.createString("bla") (псевдо). На заводе есть пул всех строк, созданных таким образом.

Если он вызывается, он проверяет, есть ли уже строка в пуле с этим значением. Если true, он возвращает этот строковый объект, поэтому строки, полученные таким образом, действительно являются одним и тем же объектом.

Если нет, он создает внутренний объект строки внутри, сохраняет его в пуле и затем возвращает его. Таким образом, когда в следующий раз запрашивается одно и то же строковое значение, он возвращает тот же экземпляр.

Вручное создание new String("") переопределяет это поведение путем обхода пула строковых литералов. Поэтому равенство всегда следует проверять с помощью equals(), который сравнивает последовательность символов вместо равенства ссылок на объекты.

1
ответ дан b_erb 25 August 2018 в 16:20
поделиться

JLS

Концепция называется «интернированием» JLS.

Соответствующий отрывок из JLS 7 3.10.5 :

Кроме того, строковый литерал всегда ссылается на тот же экземпляр класса String. Это связано с тем, что строковые литералы, или, в более общем смысле, строки, которые являются значениями константных выражений (§15.28), «интернированы», чтобы обмениваться уникальными экземплярами, используя метод String.intern.

Пример 3.10.5-1. Строковые литералы

Программа, состоящая из блока компиляции (§7.3):

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}
class Other { static String hello = "Hello"; }

и блок компиляции:

package other;
public class Other { public static String hello = "Hello"; }

создает вывод:

true true true true false true

JVMS

JVMS 7 5.1 говорит :

Строковый литерал является ссылкой к экземпляру класса String и выводится из структуры CONSTANT_String_info (§4.4.3) в двоичном представлении класса или интерфейса. Структура CONSTANT_String_info дает последовательность кодовых точек Unicode, составляющих строковый литерал.

Язык программирования Java требует, чтобы идентичные строковые литералы (то есть литералы, которые содержат одну и ту же последовательность кодовых точек) должны относиться к тому же экземпляр класса String (JLS §3.10.5). Кроме того, если метод String.intern вызывается в любой строке, результатом является ссылка на тот же экземпляр класса, который будет возвращен, если эта строка появилась как литерал. Таким образом, следующее выражение должно иметь значение true:

("a" + "b" + "c").intern() == "abc"

Чтобы получить строковый литерал, виртуальная машина Java проверяет последовательность кодовых точек, заданную структурой CONSTANT_String_info.

  • Если метод String.intern ранее был вызван в экземпляр класса String, содержащий последовательность кодовых точек Unicode, идентичную последовательности, заданной структурой CONSTANT_String_info, тогда результат строкового литерала является ссылкой на тот же экземпляр class String.
  • В противном случае создается новый экземпляр класса String, содержащий последовательность кодовых точек Unicode, заданную структурой CONSTANT_String_info; ссылка на этот экземпляр класса является результатом строкового литерала. Наконец, вызывается метод intern нового экземпляра String.

Bytecode

Также полезно посмотреть на реализацию байт-кода на OpenJDK 7.

Если мы декомпилируем:

public class StringPool {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == c);
    }
}

, мы имеем в пуле констант:

#2 = String             #32   // abc
[...]
#32 = Utf8               abc

и main:

 0: ldc           #2          // String abc
 2: astore_1
 3: ldc           #2          // String abc
 5: astore_2
 6: new           #3          // class java/lang/String
 9: dup
10: ldc           #2          // String abc
12: invokespecial #4          // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne     42
38: iconst_1
39: goto          43
42: iconst_0
43: invokevirtual #7          // Method java/io/PrintStream.println:(Z)V

Обратите внимание:

  • 0 и 3: загружена константа ldc #2 (литералы)
  • 12: новая строка экземпляр создается с помощью #2 в качестве аргумента)
  • 35: a и c сравниваются как обычные объекты с if_acmpne

представление постоянных строк довольно магия на байт-коде:

  • у него есть специальная структура CONSTANT_String_info , в отличие от обычных объектов (например, new String)
  • struct указывает на CONSTANT_Utf8_info Structure , которая содержит данные. Это единственные необходимые данные для представления строки.

и приведенная выше цитата JVMS говорят, что всякий раз, когда указатель Utf8 одинаковый, то идентичные экземпляры загружаются с помощью ldc.

Я сделал аналогичные тесты для полей и:

  • static final String s = "abc" указывает на таблицу констант через ConstantValue Attribute
  • не конечные поля не имеют этого атрибута, но все еще могут быть инициализированы с помощью ldc

. Заключение: имеется прямая поддержка байт-кода для пула строк и представление памяти

Бонус: сравните это с пулом Integer , который не имеет поддержки прямого байт-кода (т. е. аналога CONSTANT_String_info).

8
ответ дан Ciro Santilli 新疆改造中心 六四事件 法轮功 25 August 2018 в 16:20
поделиться

Хотя он выглядит одинаково с точки зрения программистов, он имеет большое влияние на производительность. Вы хотели бы использовать первую форму почти всегда.

0
ответ дан fastcodejava 25 August 2018 в 16:20
поделиться
String str = new String("hello")

Он проверит, содержит ли пул константных строк String "hello"? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул строк String.

Объект будет создан в области памяти кучи, а str указывает на объект, созданный в ячейке памяти кучи.

, если вы хотите str ссылаться на объект точки, содержащийся в Строковый пул констант, то нужно явно вызвать str.intern();

String str = "world";

. Он проверит, содержит ли пул констант String уже строку «hello»? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул констант String.

В обоих случаях регистр str указывает на String "world", присутствующий в пуле констант.

0
ответ дан Jayesh 25 August 2018 в 16:20
поделиться

@Braj: Я думаю, вы упоминали об этом наоборот. Пожалуйста, исправьте меня, если я ошибаюсь

Создание объекта по строкам:

String str1 = new String ("java5")

   Pool- "java5" (1 Object)

   Heap - str1 => "java5" (1 Object)

String str2 = "java5"

  pool- str2 => "java5" (1 Object)

  heap - str1 => "java5" (1 Object)

String str3 = new String (str2)

  pool- str2 => "java5" (1 Object)

  heap- str1 => "java5", str3 => "java5" (2 Objects)

Строка str4 = "java5"

  pool - str2 => str4 => "java5" (1 Object)

  heap - str1 => "java5", str3 => "java5" (2 Objects)
1
ответ дан SDC 25 August 2018 в 16:20
поделиться

Один простой способ понять разницу ниже: -

String s ="abc";
String s1= "abc";
String s2=new String("abc");

        if(s==s1){
            System.out.println("s==s1 is true");
        }else{
            System.out.println("s==s1 is false");
        }
        if(s==s2){
            System.out.println("s==s2 is true");
        }else{
            System.out.println("s==s2 is false");
        }
Выход

-

s==s1 is true
s==s2 is false

Таким образом, новый String () всегда будет создавать новый экземпляр.

1
ответ дан Shashank T 25 August 2018 в 16:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: