Страницы

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

понедельник, 3 февраля 2020 г.

Вопросы по передаче параметров в Java

#java


Здравствуйте! Пересев с С# узнал, что в Java все параметры передаются по значению. 

1) Ссылка ссылается на имеющийся объект, и если до передачи на него ссылалась одна
ссылка, то теперь их две? 

2) Создаётся новый объект в куче, и в пределах блока кода метода работаешь с новосозданным
объектом. При этом после завершения работы метода, изначальный объект остаётся не изменённым?
Созданный объект в методе уже стал на учёте у сборщика мусора?

Прочитав пару статей про передачу параметров в Java, решил поэкспериментировать.
Есть свой класс со строковым полем и двумя методами. Первый метод меняет поле объекта,
а второй меняет значение скопированной ссылки.

Вот класс:

class MyClass {

String s;

public MyClass(String s) {
    this.s = s;
}

public static void changeField(MyClass other) {
    other.s = "**********";
}

public static void changeRef(MyClass other) {
    other = new MyClass("----------");
} 


Однако почему-то, метод changeField изменяет объект, в то время как changeRef - нет.

    MyClass obj1 = new MyClass("1");
    MyClass obj2 = new MyClass("2");

    MyClass.changeField(obj1);
    MyClass.changeRef(obj2);

    System.out.println(obj1.s);
    System.out.println(obj2.s);


Вывод исполнения программы: 

**************
2 

    


Ответы

Ответ 1



Как вы сказали, в Java передаётся ссылка на объект(за исключением примитивных классов типа int, long and etc.) при этом, под эту ссылку выдается своя память. В методе changeField происходит изменение самого объекта. И вы видите эти изменения за пределами функции. В методе changeRef происходит создание нового экземпляра класса и ссылку на него записываете в ту область памяти которая была выделена для копии ссылки передаваемого объекта. Таким образом вы не меняете исходную ссылку и исходный объект. И да, при передаче объекта в метод, создаётся дополнительная ссылка, т.е. их становится две, как вы написали в вашем вопросе.

Ответ 2



В java нет передачи по ссылке в том смысле, что члены ссылочных типов вы менять можете, а вот сами ссылки, указывающие на экземпляры этих типов - нет. В C# по сути все точно так же: тот же самый код, что вы написали, будет точно так же работать и там. При вызове changeField вы меняете поле экземпляра, но не сам экземпляр. А при вызове changeRef вы пытаетесь изменить саму ссылку, но ссылки остаются неизменными, так как в метод вы передаете только их копии. Отличие между Java и C# будет в том, что C# с помощью ключевых слов ref и out позволяет менять и сами ссылки на объекты. В java этого нет

Ответ 3



Всетаки букварь по Java прочитать стоит. Все передается по значению. В java нет передачи по ссылке. Вот только MyClass obj1 = new MaClass("1") означает что в obj1 лежит не объект а ссылка на него. В тоже время long val = 1l означает что в val храниться 1, но Long val = new Long(1) - уже будет означать что val храниться ссылка на объект типа Long ( не путать с примитивным типом long) Вот тут подробнее https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html Т.е. разница между Reference types и Primitive Types

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

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