String a = new String("A");
String b = a; //b указывает на "A"
b = "B"; //b указывает новую строку "B"
LJ>Имеется код: LJ>
LJ>public class TestConsole
LJ>{
LJ> public static void main(String[] args)
LJ> {
LJ> Foo ob = new Foo();
LJ>//в следующей строке получаем указатель на "123"
LJ> String str = ob.getString();
LJ> System.out.println(ob.getString());
LJ>//здесь мы меняем указатель внешней переменной - создаем новый String объект! при этом ob.m_Str указывает на старый объект.
LJ> str = "321";
LJ> System.out.println(ob.getString());
LJ> }
LJ>}
LJ>
P.S.: смотрим в JLS
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[6]: Метод возвращает ссылку на объект, а далее...
Может быть, я опять покажусь педантичным, но в цитируемом источнике есть неточности. Во второй строке новый объект не создается. К этому моменту он уже имеется созданный и лежит в пуле строк. А в пул строк он попадает в момент загрузки класса (если его там еще не было). В доказательство справедливости этого можно выполнить такой код
String a, b;
a = "hello";
b = "hello";
System.out.println(a == b);
Если бы всякий раз, когда встречается строковый литерал, создавался бы новый объект, результатом выполнения данного кода был бы вывод false. Тем не менее код выводит true, а это означает, что новый объект не создается.
RI>Да нет. В том то и дело, что java.lang.String является немодифицируемым. То есть объект, который создался он уже таким и будет, а при попытке новых присвоений просто создаются новые объекты, выделяется память, получаем на нее ссылку.
RI>Вы же не хотите сказать, что любой класс не может изменять какие-то свои данные? А вот стринг не может. Так что особый.
Я хочу сказать, что в данном случае немодифицируемость String никакой роли не играет.
Re[6]: Метод возвращает ссылку на объект, а далее...
Ok, заменив String на какой-нибудь модифицируемый класс в примере автора топика, что нибудь изменится принципиально? Разве Foo.m_Str изменит свое значение? Будь там хоть String, хоть HashMap, хоть List...
Re[2]: Метод возвращает ссылку на объект, а далее...
Дело в том что спецификация JVM гарантирует что для всех равных константых строк будет использоваться один и тот же обьект.
Поэтому в первом случае результат сравнения ссылок true.
Во втором же создается новый обьект. в котором как видно из кода содержится либо такой же массив байт.
Либо новый массив с таким же как и у исходной строки содержимым.
Т.е при использовании
String str1 = "bla";
String str2 = "bla";
обьект один, а при использовании
String str1 = "bla";
String str2 = new String(str1);
обьектов два.
впрочем при сравнении их методом equals результат будет true.
/**
* Initializes a newly created <code>String</code> object so that it
* represents the same sequence of characters as the argument; in other
* words, the newly created string is a copy of the argument string. Unless
* an explicit copy of <code>original</code> is needed, use of this
* constructor is unnecessary since Strings are immutable.
*
* @param original a <code>String</code>.
*/public String(String original) {
this.count = original.count;
if (original.value.length > this.count) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.this.value = new char[this.count];
System.arraycopy(original.value, original.offset,
this.value, 0, this.count);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.this.value = original.value;
}
}
Re[2]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, tantalum, Вы писали:
T>Здравствуйте, all-x, Вы писали:
AX>>Здравствуйте, tantalum, Вы писали:
T>>>Проще обьяснить так — хотя String и является Object, он передается по значению, а не по ссылке.
AX>>Категорически не верно. Такое объяснение только запутывает. AX>>По способу передачи String ничем не отличается от любого другого reference type.
T>Сорри... жестко стормозил! без внимания прочитал код. T>Я имел в виду след. случай T>...... T>... T>public static void main(String[] args){ T> String str = "123"; T> doSome(str) T> System.out.println(str); T>} T>public void doSome(String str){ T> str+="456"; T>} T>..... T>На экране будет 123, а не 123456.
Здесь имеет значение то, что содержимое объекта класса String изменить нельзя
и операция += записывает параметр метода ссылку на новый объект.
А локальная переменная метода main по-прежнему содержит ссылку на старый объект,
который и печатается. Строки всё равно передаются по ссылке.
Re[4]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, RI, Вы писали:
RI>Да нет. В том то и дело, что java.lang.String является немодифицируемым. То есть объект, который создался он уже таким и будет, а при попытке новых присвоений просто создаются новые объекты, выделяется память, получаем на нее ссылку.
RI>Вы же не хотите сказать, что любой класс не может изменять какие-то свои данные? А вот стринг не может. Так что особый.
Тогда любой неизменяемый класс особый, и java.lang.Integer, и java.lang.Character... и свой можно написать, чтобы он был особым в таком смысле.
--
Дмитро
Re[7]: Метод возвращает ссылку на объект, а далее...
D>Может быть, я опять покажусь педантичным, но в цитируемом источнике есть неточности. Во второй строке новый объект не создается. К этому моменту он уже имеется созданный и лежит в пуле строк. А в пул строк он попадает в момент загрузки класса (если его там еще не было). В доказательство справедливости этого можно выполнить такой код D>
D>Если бы всякий раз, когда встречается строковый литерал, создавался бы новый объект, результатом выполнения данного кода был бы вывод false. Тем не менее код выводит true, а это означает, что новый объект не создается.
Все там правильно. Цитирую дальше:
----------------------------------
Поскольку каждый строковый литерал порождает новый объект, что есть очень
ресурсоемкая операция в Java, то зачастую компилятор стремится оптимизировать эту
работу.
Во-первых, если используются несколько литералов с одинаковым значением, то для всех
них будет создан один и тот же объект.
Если вы пришли из С++, то вам будет проще понять, что происходит, если думать о str как о указателе. Вы просто присвоили указателю адрес на другую строку.
LJ>Непонятно, почему не изменился объект Foo::m_Str? Ведь метод Foo::getString() возвращает ссылку, которой я присваиваю новую строку.
LJ>P.S. LJ>А есть разница? LJ>
LJ>private String m_Str = "123"; //Так
LJ>private String m_Str = new String("123"); //И так
LJ>
LJ>Спасибо!
Проще обьяснить так — хотя String и является Object, он передается по значению, а не по ссылке.
Re[2]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, all-x, Вы писали:
AX>Здравствуйте, tantalum, Вы писали:
T>>Проще обьяснить так — хотя String и является Object, он передается по значению, а не по ссылке.
AX>Категорически не верно. Такое объяснение только запутывает. AX>По способу передачи String ничем не отличается от любого другого reference type.
Сорри... жестко стормозил! без внимания прочитал код.
Я имел в виду след. случай
......
...
public static void main(String[] args){
String str = "123";
doSome(str)
System.out.println(str);
}
public void doSome(String str){
str+="456";
}
.....
На экране будет 123, а не 123456.
Re[4]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, tantalum, Вы писали:
T>>>Проще обьяснить так — хотя String и является Object, он передается по значению, а не по ссылке.
AX>>Категорически не верно. Такое объяснение только запутывает. AX>>По способу передачи String ничем не отличается от любого другого reference type.
T>Я имел в виду след. случай
Здравствуйте, dshe, Вы писали:
D>Здравствуйте, tantalum, Вы писали:
T>>>>Проще обьяснить так — хотя String и является Object, он передается по значению, а не по ссылке.
AX>>>Категорически не верно. Такое объяснение только запутывает. AX>>>По способу передачи String ничем не отличается от любого другого reference type.
T>>Я имел в виду след. случай D>
T>>На экране будет 123, а не 123456.
D>Ну так он здесь тоже не по значению передается, а по ссылке (как и любой другой reference type). А поскольку String immutable, то выражение D>
D>str+="456";
D>
D>на самом деле представляется так: D>
D>str = new StringBuilder().append(str).append("456").toString();
D>
D>т.е. старое значение "123" не изменяется, а заменяется новым "123456".
Пацаны, да что вы мне все разъеснить-то наровите??? Знаю!!! я же написал ПРОЩЕ обьяснить.....!!!!
Re[3]: Метод возвращает ссылку на объект, а далее...
F>>"A String object has a constant (unchanging) value" F>>т.е. присвоение (="321") просто создает новую строку
U>Ну зачем человека путать. Тут дело вовсе не в том, что String какой-то особый- с любым другим объектом другого класса ситуация будет такая-же.
Да нет. В том то и дело, что java.lang.String является немодифицируемым. То есть объект, который создался он уже таким и будет, а при попытке новых присвоений просто создаются новые объекты, выделяется память, получаем на нее ссылку.
Вы же не хотите сказать, что любой класс не может изменять какие-то свои данные? А вот стринг не может. Так что особый.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: Метод возвращает ссылку на объект, а далее...
Еще одним важным свойством этого класса является неизменяемость. Это означает, что,
породив объект, содержащий некое значение-строку, мы уже не можем изменить это
значение, для этого необходимо создать новый объект.
String s="a";
s="b";
Во второй строке переменная сменила свое значение, но только создав новый объект
класса String.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, ukman, Вы писали:
U>Ok, заменив String на какой-нибудь модифицируемый класс в примере автора топика, что нибудь изменится принципиально? Разве Foo.m_Str изменит свое значение? Будь там хоть String, хоть HashMap, хоть List...
Весь прикол в том, что там мы явно вызываем конструктор и все понимают, что создан новый объект.
А тут у автора топика возникал вопрос:
U>А есть разница? U>private String m_Str = "123"; //Так U>private String m_Str = new String("123"); //И так
Вот чтобы не возникало непоняток, я и написал.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Метод возвращает ссылку на объект, а далее...
Здравствуйте, zubr, Вы писали:
Z>Здравствуйте, LearnJava, Вы писали: Z>
Z>String a = new String("A");
Z>String b = a; //b указывает на "A"
Z>b = "B"; //b указывает новую строку "B"
Z>
LJ>>Имеется код: LJ>>
LJ>>public class TestConsole
LJ>>{
LJ>> public static void main(String[] args)
LJ>> {
LJ>> Foo ob = new Foo();
LJ>>//в следующей строке получаем указатель на "123"
LJ>> String str = ob.getString();
LJ>> System.out.println(ob.getString());
LJ>>//здесь мы меняем указатель внешней переменной - создаем новый String объект! при этом ob.m_Str указывает на старый объект.
LJ>> str = "321";
LJ>> System.out.println(ob.getString());
LJ>> }
LJ>>}
LJ>> Z>P.S.: смотрим в JLS
вроде правильно говоришь, только я бы тебе минус поставил бы. надо человеку объяснить как идет передача ссылочных переменных.