![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Так как в яве все объекты передаются по ссылке, то подскажите, как с этим правильно работать?
Как правильно использовать clone()? etc... -------------------- |
|||
|
||||
| Sun |
|
|||
|
Account removed ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1611 Регистрация: 14.8.2002 Репутация: 8 Всего: 48 |
На самом деле утверждение что в Java объекты передаются по ссылке не совсем верно, во всяком случае ссылка в Java это не тоже самое что ссылка в C++. Можно провести простой эксперимент подтверждающий это
В этом примере вместо "Test" будет выведено "blah-blah", тогда как в подобном коде на C++ с использованием ссылок будет выведено слово "Test". Похоже что при передаче объекта в метод происходит его клонирование. -------------------- Account removed |
|||
|
||||
| AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Правильно работать - это значит знать и помнить, что все изменения, которые ты сделаешь будут относится к переданному объекту. Больше тут особо советовать нечего.
А по поводу clone() : Есть Cloneable специальный интерфейс, который дол;ен быть реализован если хочется создавать копию объекта. Если класс реализует Cloneable, то это говорит о том, что при вызове clone() будет создана копия обекта. Обычное присвоение для объекта оператором присваивания (=) фактически является перенаправлением ссылки, а не копированием полей из одного объекта в другой. Лучше всего почитать прямо в Java API об интерфейсе Cloneable и методе Object.clone(). |
|||
|
||||
| Sun |
|
|||
|
Account removed ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1611 Регистрация: 14.8.2002 Репутация: 8 Всего: 48 |
Вот нашел небольшую статью, утверждающую что "ВСЕ ПАРАМЕТРЫ В JAVA ПЕРЕДАЮТСЯ ПО ЗНАЧЕНИЮ".
http://www.javable.com/columns/robinson/letters/01/ Думаю с автором можно согласиться, правда не стоит говорить такого при тестировании или устройстве на работу -------------------- Account removed |
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Спасибо обоим
-------------------- |
|||
|
||||
| AntonSaburov |
|
||||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
В данном случае происходит создание нового объекта типа String и ссылка переданная в качестве параметра теперь указывает просто на новый объект. Тут важно отметить, что передаваемая ссылка и ссылка как аргумент - это разные ссылки. Т.е происходит копирование ссылки. Можно посмотреть на такой код:
Здесь интересен момент когда в ShowMe переменной mc присваивается указатель на новый объект. Т.е. теперь mc указывает уже на совсем другую переменную. И здесь тогда сразу видно, что переменная my2 в main и переменная mc как аргумент ShowMe - это две разные переменные-ссылки. Просто в первый момент вызова ShowMe они обе указывают на один и тот же объект. Вот и получаем эффект, который показан в примере Sun |
||||
|
|||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Я столкнулся с таким вот :
Создаю новый объект моего типа. myClass myObj=(myClass)myArray.get(n); По идее - объект новый, но изменив в нем значения полей, они изменятся и в myArray[n] То есть копирования не происходит, в myObj передается ссылка на объект из myArray[n] Это сообщение отредактировал(а) Alone - 16.12.2003, 18:12 -------------------- |
|||
|
||||
| daniel (yerevan| javaxp@ya |
|
|||
|
Unregistered |
yourClass ob1=new yourClass();
yourClas ob2; ob2=ob1; //ssylka na pamyat ob1 // ob1=null // ob2 sushestvuet |
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Дело в том, что в данной реализации моего кода я не передаю объект в качестве параметра.
Он у меня объявлен паблик. Может это и некорректно, но мне так проще к нему обращаться. Поэтому, для работы с ним, мне надо его скопировать(клонировать) для обеспечения возможности отмены изменений объекта. -------------------- |
|||
|
||||
| AntonSaburov |
|
||||||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Так ты его не создаешь. Ты создаешь еще одну ссылку указывающую на один и тот же объект. А для создания копии надо честно скопировать все поля из одного объекта в другой. Т.е. если имеем объект
то копирование объекта в другой будет подобно
Причем стоит отметить следующее - если объект внутри себя имеет сылки на объекты (поле типа Object и все, что дальше по наследованию), то опять же простое присваивание таких полей сделает следующее: ссылки во втором объекте будут указывать на тот же объект, что и в первом. |
||||||
|
|||||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
И всётаки... Что в этом случае лучше/корректней/проще/вернее сделать?
1. реализовать cloneable? 2. копировать ручками ( а если структура >20полей?, да и код увеличивается...) -------------------- |
|||
|
||||
| Alone |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Вот, добрался до реализации Cloneable...
В связи с этим возникли вопросы: Для решения проблемы клонирования, объект должен реализовать метод clone() Делаем...
Идем дальше:
И наконец в главном коде:
-------------------- |
||||||
|
|||||||
| AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Надо копировать список - и ручками. Т.е. создать новый список и скопировать туда содержимое из оригинала. Иначе никак не получится.
super.clone может копировать ТОЛЬКО primitive поля (int, double, long) |
|||
|
||||
| Alone |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Хорошо, как тогда объяснить такое:
объект1
объект2
главный класс
результат выполнения: [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 Получилась "правильная" копия листа... не ссылки, а новые объекты! О, как! -------------------- |
||||||
|
|||||||
| Alone |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Извиняюсь, ошибочка вышла... (с)Охота
вот здесь
а надо вот так:
и результат плачевный [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 -------------------- |
||||
|
|||||
| Alone |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
УРА! поборол таки!
рассказываю фсем: в класс, который предполагается клонировать, надо имплементить интерфейс Cloneable и реализовать его метод clone() Если в классе встречается поле типа массива, то в реализуемом методе clone() надо 1. создать новый массив 2. в цикле клонируем все элементы массива 3. заменяем поле типа массив новым массивом 4. возвращаем клонированный объект пример:
а вот класс, который является элементом массива
Теперь если у нас есть объект personRow a=(personRow)AnyArray.get(i); Мы смело можем его клонировать! personRow b=(personRow)a.clone(); Это сообщение отредактировал(а) Alone - 18.12.2003, 14:46 -------------------- |
||||
|
|||||
| AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Так я тебе это и пытался все это время втолковать - надо фактически создать новый объект и честно скопировать все поля. Если поля имеют сложный тип, то надо создавать объект этого типа и опять делать копию. И так далее.
|
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Кстати, я опять ошибся
класс LinkedList уже имплементит Cloneable, и в нем есть реализация метода clone Только выполняет он таки "поверхностное" копирование, то бишь лепит ссылку... Фууух... блин, как тяжко... Это сообщение отредактировал(а) Alone - 18.12.2003, 15:52 -------------------- |
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Насколько я понял, для этого надо "сложный тип" делать клонируемым. -------------------- |
|||
|
||||
| AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
Можно делать, а можно в лоб копировать все. Тут уже как хочешь. Но как ты сам видел многие стандартные JAVA-классы делают "shallow copy" (поверхностная копия). А в твоем случае потребовалось "deep copy" (глубокая копия) (перевод само собой условный). Вот ты и нарвался. Впрочем это как раз в описании Object.clone() очень подробно расписано. |
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
Да я просто в исходник LinkedList глянул
Кстати, по ходу дела вопрос. почему надо делать именно так: java.util.List myList = new java.util.LinkedList(); а не так: java.util.LinkedList myList = new java.util.LinkedList(); У? Почему обявление - интерфейсом, а нью - классом? -------------------- |
|||
|
||||
| AntonSaburov |
|
|||
![]() Штурман ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5658 Регистрация: 2.7.2002 Где: Санкт-Петербург Репутация: 51 Всего: 118 |
new классом - а иначе просто никак. А вот почему надо делать ? Я бы сформулировал так - почему так делают ? Ссылка на интерфейс говорит о том, что мы будем использовать созданный класс только для работы именно с этим интерфейсом. И никак иначе. В таком случае код получается более защищенным и мобильным. Вдруг ты захочешь использовать для этого интерфейса другой класс ? Просто замени его в операторе new. И тебе тогда нельзя будет использовать методы созданного объекта, которые он получил от класса. Значит ты получаешь более защищенный код. Вот вообщем-то основные мысли по этому поводу. И больше в этом топике вопросы не по теме не надо - против правил не стоит идти |
|||
|
||||
| Alone |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 663 Регистрация: 11.5.2003 Где: Dnepropetrovsk, U A Репутация: 3 Всего: 6 |
За оффтоп понял, за остальное - спасибо.
Тема в принципе исчерпана. -------------------- |
|||
|
||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |