Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Непонятный код


Автор: maddoc 7.4.2006, 22:57
кто объяснит ответ
Код

class GFC301 {
  private String name;
  public GFC301(String name) {this.name = name;}
  public void setName(String name) {this.name = name;}
  public String getName() {return name;}
  public static void m1(GFC301 r1, GFC301 r2) {
    r1.setName("Bird");
    r2 = r1;
  }
  public static void main (String[] args) {
    GFC301 pet1 = new GFC301("Dog");
    GFC301 pet2 = new GFC301("Cat");
    m1(pet1,pet2);
    System.out.println(pet1.getName() + "," + pet2.getName());
}}


ответ Bird,Cat

Автор: LSD 7.4.2006, 23:10
В функцию передаются ссылки на объекты, причем передаются по значению. Т.е. код:
Код
r2 = r1;

локальной ссылке на r2 присваивает значение r1. Но поскольку дальше мы этими ссылками не оперируем, то этот кусок кода можно закомментарить и ничего не изменится.
Ранее мы меняем значение поля name:
Код
r1.setName("Bird");

причем меняем у исходного объекта (что видно из System.out.println()).

Вообщем, никаких аномалий в поведении объектов не замечено smile

Автор: Tirael 7.4.2006, 23:26
И почему непонтно ?
Давай проследим цепочку действий:

Входной точкой ( началом ) программы является функция main. Ее код
Код

public static void main (String[] args) {    
    GFC301 pet1 = new GFC301("Dog");    
    GFC301 pet2 = new GFC301("Cat");    
    m1(pet1,pet2);    
    System.out.println(pet1.getName() + "," + pet2.getName());    
}


1 Создаем объект pet1
Код

GFC301 pet1 = new GFC301("Dog");

Причем как видишь в конструктор пишем "Dog". Значит после этой операции у нас будет у нас будет объект pet1, с полем name равном "Dog"

Код конструктора:
Код

public GFC301(String name) {this.name = name;}


2
Делаем тоже самое, но уже объект pet2 и конструктору передаем "Cat"

Значит у нас два разных объекта, pet1 и pet2, поле которых name соответсвенно равно "Dog" и "Cat"

3
Далее вызываем функцию m1 этого же класса
Код

m1(pet1,pet2);


Давай поподробнее рассмотрим код этой функции
Код

public static void m1(GFC301 r1, GFC301 r2) {    
    r1.setName("Bird");    
    r2 = r1;    
  }

Она берет два параметра, а именно ссылки на объект типа GFC301 ( в нашем случае это ссылки pet1 и pet2 ). Заметим так же важную вещь, то что ссылки r1 и r2 это совершенно самостоятельные ссылки. И действительны они только в пределах функции m1 .В данном случае они просто будут ссылаться на те же объекты, что и ссылки pet1 и pet2. Далее вызываем метод setName("Bird");
Код

public void setName(String name) {this.name = name;}

Значит в первом объекте поле name теперь будет не "Dog", а "Bird".
Следующая строчка - это просто подвох.
Код

r2 = r1;

Теперь r1 и r2 ссылаются на один и тот же объект. Но заметь, никаких данных внутри объекта мы не меняли. А значит по окончании работы этого метода у нас будут два объекта. у первого поле name будет равно "Bird", a у второго "Cat"

4 Возврящемся в функцию main и выполняем следующую команду :
Код

System.out.println(pet1.getName() + "," + pet2.getName());

Она выводит на экран содержимое поля name первго и второго объектов.
Восему мы получаем Bird,Cat

Автор: maddoc 7.4.2006, 23:27
А разве по знчению передаются не простые типы?

Автор: LSD 7.4.2006, 23:29
Цитата(maddoc @ 8.4.2006, 00:27 Найти цитируемый пост)
А разве по знчению передаются не простые типы?

Простые типы, по значению. Но тут нет ни одного простого типа.

Автор: Tirael 7.4.2006, 23:33
Цитата(maddoc @ 7.4.2006, 23:27 Найти цитируемый пост)
А разве по знчению передаются не простые типы?


По значению передаются только простые типы. ( int, char, double и т.д. )
В нашем случае тип GFC301 не простой. И объекты будут передаваться по ссылке и только по ссылке.

Блин, меня опять опередили. smile Надо будет делать пустой пост, а потом сидеть его редактриковать )))

Автор: maddoc 7.4.2006, 23:34
Цитата

В функцию передаются ссылки на объекты, причем передаются по значению.

smile smile smile ???????
2 Tirael
Цитата

Но заметь, никаких данных внутри объекта мы не меняли.

так а зачем менять, если 2 ссылки на 1 обьект? (или я что-то не так понял)

Автор: Tirael 7.4.2006, 23:41
maddoc,

Цитата(maddoc @ 7.4.2006, 23:34 Найти цитируемый пост)
В функцию передаются ссылки на объекты, причем передаются по значению.

Наверное, имелось ввиду что ссылка, это тоже какой то набор битов и байтов в памяти компьютера. Просто первый набор битов копируется и получается в точности такой же набор битов, но уже в другой области памяти. Названный по другому. Хочешь назови этот набор битов "значением" ссылки.

Цитата

так а зачем менять, если 2 ссылки на 1 обьект? (или я что-то не так понял)

Так менять и не зачем. Это подвох. Ты все правильно понял.

Автор: maddoc 7.4.2006, 23:52
Спасибо всем, я все понял smile
дело именно в том, что внутри метода все равно копии ссылок
а так как в r2(внутри метода) присвоили другую ссылку, от этого r2 базовый не поменяется.
кажется так?

Автор: LSD 8.4.2006, 00:03
Цитата(Tirael @ 8.4.2006, 00:33 Найти цитируемый пост)
Блин, меня опять опередили.  Надо будет делать пустой пост, а потом сидеть его редактриковать )))

Не стоит, возможно твой ответ будет более развернутым или более понятным smile

Манипуляции с объектами в Java осуществляются только по ссылкам, а объекты создаются только в куче.
Например на 32-х битных процессорах ссылка, это 32-х битное безнаковое целое, которое адресует некий адрес в памяти. Когда мы вызываем метод и передаем ему некоторые переменные, то в стек помещяются копии этих ссылок (потом по ним можно получить объекты, на которые они ссылаются). Если метод присваивает ссылкам новые значения, то он меняет локальные копии из стека, на исходные значения ссылок он повлиять он не может. Но метод может по ссылке получить объект и изменить его состояние.

Автор: LSD 8.4.2006, 16:58
Я вынес оффтопик в http://forum.vingrad.ru/index.php?showtopic=91024 тему.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)