Самое простое решение - создать функцию 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);
});
new String("text");
явно создает новый и ссылочно выделенный экземпляр объекта String
; String s = "text";
может повторно использовать экземпляр из пула строковых констант, если он доступен.
Вы очень редко хотели бы использовать конструктор new String(anotherString)
. Из API:
String(String original)
: Инициализирует вновь созданный объектString
, чтобы он представлял ту же последовательность символов, что и Аргумент; Другими словами, вновь созданная строка является копией строки аргумента. Если явная копия оригинала не нужна, использование этого конструктора необязательно, поскольку строки неизменяемы.Связанные вопросы
- Строки Java: «String s = new String (« глупо »);«
- Строки - это объекты в Java, поэтому почему мы не используем «новое» для их создания?
Что означает референциальное различие
Изучите следующий фрагмент:
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)
. Однако необходимо повторить, что это очень своеобразно и редко является намерением.Ссылки
Связанные с этим вопросы
Строковые литералы войдут в String Constant Pool.
Следующий снимок может помочь вам понять его визуально , чтобы запомнить его в течение более длительного времени.
[/g3]
Создание объектов по строкам:
String str1 = new String("java5");
Используя строковый литерал «java5» в конструкторе, новое строковое значение сохраняется в пуле строковых констант. Используя новый оператор, в куче создается новый строковый объект с «java5» в качестве значения.
String str2 = "java5"
Ссылка «str2» указана на уже сохраненное значение в пуле константных строк
String str3 = new String(str2);
В куче создается новый строковый объект с тем же значением, что и ссылка на «str2»
String str4 = "java5";
Ссылка «str4» указана на уже сохраненное значение в пуле константных строк
Всего объектов: куча - 2, пул - 1
Один создает String в String Constant Pool
String s = "text";
, другой создает строку в пуле констант ("text"
) и другую строку в обычной куче пространство (s
). Обе строки будут иметь то же значение, что и «текст».
String s = new String("text");
s
затем теряется (подходит для GC), если позже не используется.
Строковые литералы, с другой стороны, используются повторно. Если вы используете "text"
в нескольких местах вашего класса, это будет фактически одна и только одна строка (т. Е. Несколько ссылок на одну и ту же строку в пуле).
Подумайте, что "bla"
является волшебной фабрикой, например Strings.createString("bla")
(псевдо). На заводе есть пул всех строк, созданных таким образом.
Если он вызывается, он проверяет, есть ли уже строка в пуле с этим значением. Если true, он возвращает этот строковый объект, поэтому строки, полученные таким образом, действительно являются одним и тем же объектом.
Если нет, он создает внутренний объект строки внутри, сохраняет его в пуле и затем возвращает его. Таким образом, когда в следующий раз запрашивается одно и то же строковое значение, он возвращает тот же экземпляр.
Вручное создание new String("")
переопределяет это поведение путем обхода пула строковых литералов. Поэтому равенство всегда следует проверять с помощью equals()
, который сравнивает последовательность символов вместо равенства ссылок на объекты.
Концепция называется «интернированием» 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
Строковый литерал является ссылкой к экземпляру класса 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
).
Хотя он выглядит одинаково с точки зрения программистов, он имеет большое влияние на производительность. Вы хотели бы использовать первую форму почти всегда.
String str = new String("hello")
Он проверит, содержит ли пул константных строк String "hello"? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул строк String.
Объект будет создан в области памяти кучи, а str
указывает на объект, созданный в ячейке памяти кучи.
, если вы хотите str
ссылаться на объект точки, содержащийся в Строковый пул констант, то нужно явно вызвать str.intern();
String str = "world";
. Он проверит, содержит ли пул констант String уже строку «hello»? Если присутствует, то он не будет добавлять запись в пул строк String. Если нет, то он добавит запись в пул констант String.
В обоих случаях регистр str
указывает на String "world"
, присутствующий в пуле констант.
@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)
Один простой способ понять разницу ниже: -
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 () всегда будет создавать новый экземпляр.