Страницы

Поиск по вопросам

суббота, 28 декабря 2019 г.

Почему объект String не передаётся по ссылке

#java #строки


Доброго времени суток.
В консоль данный код выводит: "slipstream slip stream", а не "slipstream slipstream
stream" как я предполагал. Помогите разобраться, почему s1 после fix(String s1) не
изменила значения на "slipstream". Спасибо. ссылка

class PassS
{
    public static void main(String [] args)
    {
        PassS p = new PassS();
        p.start();
    }

    void start()
    {
        String s1 = "slip";
        String s2 = fix(s1);
        System.out.println(s1 + " " + s2);
    }

    String fix(String s1)
    {
        s1 = s1 + "stream";
        System.out.print(s1 + " ");
        return "stream";
    }
}

    


Ответы

Ответ 1



Читаем доки. Strings are constant; their values cannot be changed after they are created. Строки иммутабельны; их значение нельзя поменять после создания. s1 = s1 + "stream" в методе fix меняет лишь локальную переменную на стеке. Оригинальная строка, определённая в методе start, не меняется.

Ответ 2



В языке Java любые параметры передаются только по значению. Строки исключением не являются. Вот пример с демонстрацией передачи объекта по значению: class Ideone { String message; Ideone(String message) { this.message = message; } public static void foo (Ideone obj) { obj = new Ideone("Если бы я был передан по ссылке, вы бы увидели это сообщение."); } public static void main (String[] args) throws java.lang.Exception { Ideone obj = new Ideone("Но вы увидите вот это, потому что параметры в Java передаются по значению."); foo(obj); System.out.println(obj.message); } } Запустить пример онлайн можно тут: https://ideone.com/0upGqO

Ответ 3



Если вам необходимо изменять строку, используйте StringBuilder.

Ответ 4



Все просто! Вы создали переменную String s1 = "slip"; в методе start() и передали ее как параметр в метода fix(String s1) и в этот момент в стеке метода создалась новая переменная s1, таким образом у нас две переменные (одна вне метода fix, другая, локальная в методе fix), которые ссылаются на один объект строки. В методе fix Вы затем локальной переменной s1 присвоили ссылку на новый объект строки, в то время как переменная s1 метода start() по-прежнему ссылается на объект строки"slip". P.S. Всем, кто утверждает, что в Java все параметры передаются по значению. Так оно и есть! Важно понимать, что при передаче объекта передается копия ссылки на объект. Поэтому можно менять свойство объекта, но ни сам объект. Если бы передача была бы по ссылке, то присвоение переменной метода нового объекта отобразилась бы на всех внешних переменных, которые бы стали бы ссылаться на новый объект. Спасибо всем, кто меня поправил! Ссылка(см. Passing Reference Data Type Arguments)

Ответ 5



Вы все правильно понимаете в теории ссылочных типов и примитивов. Действительно в данном случае, исходя из общей концепции, ваша переменная должна была изменить свое значение. Вся проблема в том, что класс String объявлен как final. Про подробности использования этого ключевго слова вы можете почитать сами, но суть в том, что не, во -первых, унаследоваться от таких классов нельзя. Во -вторых, в данном случае это самое главное, вы не можете изменить ссылку на созданный объект. Т.е. каждый раз, присваивая одной и той же переменной новое значение на самом деле вы не изменяете старый объект, а создаете новый. Именно это свойство не позволяет Вам видеть передачи значения по ссылке в данном коде, ведь по сути объект типа стринг не изменился, а создался заново. Причины того, что string объявлен как final, достаточно много, основные из них состоят в обеспечении потокобезопасности, скорости работы, соблюдение требований безопасности в целом(это не позволит подменить стринг классом наследником и производить с ним какие-либо манипуляции). В целом же идею ссылочных типов и примитивов , как я уже говорил, вы поняли правильно. Чтобы убедиться в этом , поэксперементируйте с классами, не объявленными как final. Например, в качестве эксперемента, предлагаю взять ArrayList. Дополните свой код таким образом, и увидите. что передача по ссылке действительно отрабатывает... import java.util.ArrayList; class PassS { public static void main(String[] args) { PassS p = new PassS(); ArrayList list = new ArrayList<>(); list.add("one"); list.add("two"); list.add("three"); System.out.println(list); delFirstElement(list); System.out.println(list); p.start(); } void start() { String s1 = "slip"; String s2 = fix(s1); System.out.println(s1 + " " + s2); } String fix(String s1) { s1 = s1 + "stream"; System.out.println(s1 + " "); return "stream"; } static void delFirstElement (ArrayList list){ list.remove(0); } }

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

Отправить комментарий