Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ссылки... 
:(
    Опции темы
Alone
Дата 15.12.2003, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Так как в яве все объекты передаются по ссылке, то подскажите, как с этим правильно работать?
Как правильно использовать clone()? etc...


--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
Sun
Дата 15.12.2003, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 8
Всего: 48



На самом деле утверждение что в Java объекты передаются по ссылке не совсем верно, во всяком случае ссылка в Java это не тоже самое что ссылка в C++. Можно провести простой эксперимент подтверждающий это
Код

class Test {
   public static void main(String args[]) throws Exception {
       Test t = new Test();
       String s = "blah-blah";
       t.ret(s);
       System.out.println("s="+s);
   }
   protected void ret(String s) {
       s = "Test";
   }
}

В этом примере вместо "Test" будет выведено "blah-blah", тогда как в подобном коде на C++ с использованием ссылок будет выведено слово "Test".
Похоже что при передаче объекта в метод происходит его клонирование.


--------------------
Account removed
PM MAIL   Вверх
AntonSaburov
Дата 15.12.2003, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



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

А по поводу clone() : Есть Cloneable специальный интерфейс, который дол;ен быть реализован если хочется создавать копию объекта. Если класс реализует Cloneable, то это говорит о том, что при вызове clone() будет создана копия обекта.
Обычное присвоение для объекта оператором присваивания (=) фактически является перенаправлением ссылки, а не копированием полей из одного объекта в другой.

Лучше всего почитать прямо в Java API об интерфейсе Cloneable и методе Object.clone().
PM MAIL WWW ICQ   Вверх
Sun
Дата 15.12.2003, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 8
Всего: 48



Вот нашел небольшую статью, утверждающую что "ВСЕ ПАРАМЕТРЫ В JAVA ПЕРЕДАЮТСЯ ПО ЗНАЧЕНИЮ".
http://www.javable.com/columns/robinson/letters/01/
Думаю с автором можно согласиться, правда не стоит говорить такого при тестировании или устройстве на работу smile.gif


--------------------
Account removed
PM MAIL   Вверх
Alone
Дата 15.12.2003, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Спасибо обоим smile.gif


--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
AntonSaburov
Дата 15.12.2003, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Цитата
Похоже что при передаче объекта в метод происходит его клонирование.


В данном случае происходит создание нового объекта типа String и ссылка переданная в качестве параметра теперь указывает просто на новый объект.

Тут важно отметить, что передаваемая ссылка и ссылка как аргумент - это разные ссылки.
Т.е происходит копирование ссылки.

Можно посмотреть на такой код:

Код

public class MyClass
{
 public int ddd = 100;
 public static void main(String[] args)
 {
   MyClass my1 = new MyClass();
   MyClass my2 = new MyClass();
   System.out.println("Before call:"+my2.ddd);
   my1.ShowMe(my2);
   System.out.println("After call:"+my2.ddd);
 }

 public void ShowMe(MyClass mc)
 {
   mc.ddd = 200;
   System.out.println("In method:"+mc.ddd);
   mc = new MyClass();
   System.out.println("In method:"+mc.ddd);
 }
}


Здесь интересен момент когда в ShowMe переменной mc присваивается указатель на новый объект. Т.е. теперь mc указывает уже на совсем другую переменную.
И здесь тогда сразу видно, что переменная my2 в main и переменная mc как аргумент ShowMe - это две разные переменные-ссылки. Просто в первый момент вызова ShowMe они обе указывают на один и тот же объект.

Вот и получаем эффект, который показан в примере Sun
PM MAIL WWW ICQ   Вверх
Alone
Дата 16.12.2003, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Я столкнулся с таким вот :
Создаю новый объект моего типа.
myClass myObj=(myClass)myArray.get(n);
По идее - объект новый, но изменив в нем значения полей, они изменятся и в myArray[n]
sad.gif
То есть копирования не происходит, в myObj передается ссылка на объект из myArray[n]

Это сообщение отредактировал(а) Alone - 16.12.2003, 18:12


--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
daniel (yerevan| javaxp@ya
Дата 16.12.2003, 18:33 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











yourClass ob1=new yourClass();


yourClas ob2;

ob2=ob1; //ssylka na pamyat ob1
// ob1=null
// ob2 sushestvuet
  Вверх
Alone
Дата 16.12.2003, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Дело в том, что в данной реализации моего кода я не передаю объект в качестве параметра.
Он у меня объявлен паблик. Может это и некорректно, но мне так проще к нему обращаться.
Поэтому, для работы с ним, мне надо его скопировать(клонировать) для обеспечения возможности отмены изменений объекта. smile.gif


--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
AntonSaburov
Дата 16.12.2003, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Цитата
Создаю новый объект моего типа.
myClass myObj=(myClass)myArray.get(n);


Так ты его не создаешь. Ты создаешь еще одну ссылку указывающую на один и тот же объект.

А для создания копии надо честно скопировать все поля из одного объекта в другой.
Т.е. если имеем объект
Код

class MyObject
{
   public int field1;
   public int field2;
}


то копирование объекта в другой будет подобно
Код

MYObject my1 = new MyObject();

/// присваиваем значения полям

// и вот реальное копирование
MYObject my2 = new MyObject();
my2.field1 = my1.field1;
my2.field2 = my1.field2;


Причем стоит отметить следующее - если объект внутри себя имеет сылки на объекты (поле типа Object и все, что дальше по наследованию), то опять же простое присваивание таких полей сделает следующее: ссылки во втором объекте будут указывать на тот же объект, что и в первом.
PM MAIL WWW ICQ   Вверх
Alone
Дата 18.12.2003, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



И всётаки... Что в этом случае лучше/корректней/проще/вернее сделать?
1. реализовать cloneable?
2. копировать ручками ( а если структура >20полей?, да и код увеличивается...)



--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
Alone
Дата 18.12.2003, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Вот, добрался до реализации Cloneable... sad.gif
В связи с этим возникли вопросы:
Для решения проблемы клонирования, объект должен реализовать метод clone()
Делаем...
Код

public class test implements Cloneable{
 
 public int i;
 public String s;
 
 public test(){
 }

 public Object clone() {
   test clone=null;
   try {
       clone=(test) super.clone();
   }
   catch (CloneNotSupportedException e) {
       throw new InternalError(e.getMessage());
   }
   return clone;
 }

}


Идем дальше:
Код

public class test2 implements Cloneable{
 
 public String s;
 public List list    //массив элементов типа test
 
 public test(){
 }

 public Object clone() {
   test2 clone=null;
   try {
       clone=(test2) super.clone();
   }
   catch (CloneNotSupportedException e) {
       throw new InternalError(e.getMessage());
   }
   return clone;
 }

}


И наконец в главном коде:
Код

 test2 t2=new test2();
 t2.s="aaa";
 test t1=new test();
 t1.i=10;
 t1.s="aaa";
 t2.list.add(t1);
 // заполнили
 test2 tt2=new test2();
 // теперь если захотим сделать копию - что у нас выйдетconfused.gif
 tt2=(test2)t1.clone();
 // все бы хорошо, ток массив то мы получим как ссылку :(((
 // кто виноват и что делать!!!




--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
AntonSaburov
Дата 18.12.2003, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Надо копировать список - и ручками. Т.е. создать новый список и скопировать туда содержимое из оригинала. Иначе никак не получится.

super.clone может копировать ТОЛЬКО primitive поля (int, double, long)

PM MAIL WWW ICQ   Вверх
Alone
Дата 18.12.2003, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Хорошо, как тогда объяснить такое:

объект1
Код

public class mailRow implements Cloneable {
   
   /** Creates a new instance of mailRow */
   public mailRow() {
   }
   
   public Object clone() throws CloneNotSupportedException {
       mailRow clone=null;
       try {
           clone=(mailRow) super.clone();
       } catch (CloneNotSupportedException e) {
           throw new InternalError(e.getMessage());
       }
       return clone;
   }
   
   public int id;
   public String s;
}


объект2
Код

public class personRow implements Cloneable {
   
   /** Creates a new instance of personRow */
   public personRow() {
   }
   
   public Object clone() throws CloneNotSupportedException {
       personRow clone=null;
       try {
           clone=(personRow) super.clone();
       } catch (CloneNotSupportedException e) {
           throw new InternalError(e.getMessage());
       }
       return clone;
   }
   
   public int pid;
   public String name;
   public java.util.List eList=new java.util.LinkedList();
}


главный класс
Код

public class test {
   
   /** Creates a new instance of test */
   public test() {
   }
   
   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {
       personRow pRow=new personRow();
       mailRow mRow=new mailRow();
       mRow.id=1;
       mRow.s="s1";
       
       pRow.pid=1;
       pRow.name="name";
       pRow.eList.add(mRow);
       
       mRow=new mailRow();
       mRow.id=2;
       mRow.s="s2";
       pRow.eList.add(mRow);
       
       mailRow m0=(mailRow)pRow.eList.get(0);
       mailRow m1=(mailRow)pRow.eList.get(1);
       System.out.println("pRow.eList[0].id="+m0.id);
       System.out.println("pRow.eList[1].s="+m1.s);
       System.out.println("Create copy of pRow and change it");
       
       personRow pRow2=null;
       try {
           pRow2=(personRow)pRow.clone();
       }catch (CloneNotSupportedException e){
           
       }
       mailRow mm=new mailRow();
       mm.id=22;
       mm.s="s22";
       pRow2.eList.set(0,mm);
       mailRow mm1=(mailRow)pRow2.eList.get(0);
       System.out.println("pRow2.eList[0].id="+mm1.id);
       System.out.println("pRow2.eList[1].s="+mm1.s);
 System.out.println("check original");
       System.out.println("pRow.eList[0].id="+m0.id);
       System.out.println("pRow.eList[1].s="+m1.s);
       
   }
   
}



результат выполнения:

[root@alone java_tests]# java test
pRow.eList[0].id=1
pRow.eList[1].s=s2
Create copy of pRow and change it
pRow2.eList[0].id=22
pRow2.eList[1].s=s22
check original
pRow.eList[0].id=1
pRow.eList[1].s=s2

Получилась "правильная" копия листа... не ссылки, а новые объекты!
О, как!


--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
Alone
Дата 18.12.2003, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 11.5.2003
Где: Dnepropetrovsk, U A

Репутация: 3
Всего: 6



Извиняюсь, ошибочка вышла... (с)Охота

вот здесь
Код

System.out.println("pRow2.eList[0].id="+mm1.id);
System.out.println("pRow2.eList[1].s="+mm1.s);
System.out.println("check original");
System.out.println("pRow.eList[0].id="+m0.id);
System.out.println("pRow.eList[1].s="+m1.s);


а надо вот так:
Код

System.out.println("pRow2.eList[0].id="+mm1.id);
       System.out.println("pRow2.eList[1].s="+mm1.s);
 System.out.println("check original");
       m0=(mailRow)pRow.eList.get(0);
       m1=(mailRow)pRow.eList.get(1);
       System.out.println("pRow.eList[0].id="+m0.id);
       System.out.println("pRow.eList[1].s="+m1.s);


и результат плачевный sad.gif
[root@alone java_tests]# java test
pRow.eList[0].id=1
pRow.eList[1].s=s2
Create copy of pRow and change it
pRow2.eList[0].id=22
pRow2.eList[1].s=s22
check original
pRow.eList[0].id=22
pRow.eList[1].s=s2



--------------------
web developer/telecommunication specialist.
mailto: [email protected]
ICQ#28442924

PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0669 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.