Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/30: Рейтинг темы: голосов - 30, средняя оценка - 4.80
1 / 1 / 2
Регистрация: 04.08.2013
Сообщений: 83
1

Метод clone() выдает ошибку

30.09.2013, 14:29. Показов 5503. Ответов 43
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
В общем сначала я переопределяю метод clone():
Java
1
2
3
4
5
6
@Override
        public Student clone() throws CloneNotSupportedException
        {
            Student cloneStud=(Student)super.clone();
            return cloneStud;
        }
Потом создаю экземпляр этого класса , и мне необходимо создать другой объект который будет клоном первого, сделал так:
Java
1
Student student3 =(Student) student1.clone();
Но оно выдает ошибку:
CloneNotSupportedException =\
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.09.2013, 14:29
Ответы с готовыми решениями:

Каким образом работает метод clone() ?
Когда мы переопределяем метод clone, то мы вызываем super.clone(). Он должен возвращать Object,...

Выдает ошибку метод итераций
program nn; type f=function (z:real):real; var x, eps, s:real; function tralialia...

Метод Synchronize выдает ошибку
есть поток, который создается по нажатию клавиши Thr.BrsThr = new BrowserThread(true);...

Метод простой итерации выдает ошибку
Делаю вот такой пример но выдает ошибку под А и В, не могу понять в чем дело, помогите, завтра...

43
91 / 91 / 10
Регистрация: 18.05.2013
Сообщений: 265
30.09.2013, 14:41 2
Ваш класс, который быть клонированию, должен реализовывать и-с Cloneable.
Т.е. при его создании
Java
1
class Student implements Cloneable
Ну и клонировать род. класс - ИМХО, но решение мягко говоря странное ....
1
1 / 1 / 2
Регистрация: 04.08.2013
Сообщений: 83
30.09.2013, 14:53  [ТС] 3
я реализовал интерфейс....а род.клас клонировать нужно потому что нужно сделать глубокое клонирование( в классе есть поле которое на объект ссылается):
Java
1
2
3
4
5
6
7
8
public class Student implements Cloneable  {
        public static ArrayList<Student> s= new ArrayList<Student>() ;
        private String firstName;
        private String lastName;
        private String thirdName;
        private int age;
        private int rate;
        private Subject favoriteSubject;
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
30.09.2013, 15:39 4
Цитата Сообщение от edwin3d Посмотреть сообщение
Ну и клонировать род. класс - ИМХО, но решение мягко говоря странное ....
Вообще-то это для большинства случаев верное решение.
super.clone() по цепочке доходит до Object.clone(), в котором производится хардкорное копирование блоков памяти.
1
1 / 1 / 2
Регистрация: 04.08.2013
Сообщений: 83
30.09.2013, 15:46  [ТС] 5
так в чем может быть проблема?
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
30.09.2013, 15:56 6
У меня все работает:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.util.ArrayList;
 
class Subject implements Cloneable {
    @Override
    public Subject clone()  {
        try {
            Subject c = (Subject) super.clone();
            return c;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }   
}
 
class Student implements Cloneable  {
    public static ArrayList<Student> s= new ArrayList<>() ;
    private String firstName;
    private String lastName;
    private String thirdName;
    private int age;
    private int rate;
    private Subject favoriteSubject;
    
    public Student() {
        favoriteSubject = new Subject();
    }
    
    @Override
    public Student clone() {
        try {
            Student cloneStud=(Student)super.clone();
            if (favoriteSubject != null) 
                cloneStud.favoriteSubject = favoriteSubject.clone();
            return cloneStud;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
 
class Main {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = s1.clone();
        System.out.println(s1);
        System.out.println(s2);
    }
}
1
91 / 91 / 10
Регистрация: 18.05.2013
Сообщений: 265
30.09.2013, 16:19 7
2Gibby:
Поясню свою мысль.
При вызове clone() я лично предпочитаю создавать полностью новый объект, в который, через механизм конструкторов (которые отрабатывают ВСЮ цепочку родитель<>) передаются ключевые параметры старого объекта.
И как мне кажется, такой метод позволяет избежать вагона трудноуловимых проблем.

2Deodatus:
Покажите, пожалуйста, весь свой код, как вызывается, перехватите исключение и покажите вывод printStackTrace()
1
1 / 1 / 2
Регистрация: 04.08.2013
Сообщений: 83
30.09.2013, 19:35  [ТС] 8
STUDENT:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
public class Student implements Cloneable  {
        public static ArrayList<Student> s= new ArrayList<Student>() ;
        private String firstName;
        private String lastName;
        private String thirdName;
        private int age;
        private int rate;
        private Subject favoriteSubject;
        /**
         * Default constructor for this class
         */
        public Student ()
        {
        }
        /**
         * Constructor with params for this class
         */
        public Student (String fName,String lName,String tName,int newAge,int nrate, Subject sub)
        {
            this.firstName=fName;
            this.lastName=lName;
            this.thirdName=tName;
            this.age=newAge;
            this.rate = nrate;
            this.favoriteSubject = sub;
            s.add(Student.this);
        }
        @Override
        public String toString()
        {
            String rezult = "Student[surname: " + this.firstName + ", name: " + this.lastName + 
                            ", lastname: " + this.thirdName + ", age: " + this.age + ", rating: " + this.rate +
                            ", favoriteSubject: "+ this.favoriteSubject.toString() + "]";       
            return rezult;
        }
        @Override
        public int hashCode()
        {
            int hash = this.firstName.hashCode() + this.lastName.hashCode() + this.lastName.hashCode() + new Integer(this.age).hashCode() 
                        + new Integer(this.rate).hashCode() + this.favoriteSubject.hashCode();     
            return hash;
        }
        @Override
        public boolean equals(Object object)
        {
            boolean rezult = false;
            if (object == null)
            {
                rezult = false;
            }
            if (this == object)
            {
                rezult = true;
            }
            if (this.getClass() != object.getClass())
            {
                rezult = false;
            }
            else
            {
                Student stud = (Student) object;
                if (this.hashCode() == stud.hashCode())
                {
                    rezult = true;
                }
            }
            return rezult;
        }
        @Override
        public Student clone() throws CloneNotSupportedException
        {
            Student cloneStud=(Student)super.clone();
            return cloneStud;
        }
        public String compareTo(Object object)
        {
            String result= "ERROR";
            if (this.getClass() != object.getClass())
            {
                result = "ERROR";
            }
            else
            {
            Student stud = (Student) object;
                if (stud.rate>this.rate)
                {
                    result = stud.firstName + " " + stud.lastName + " " + stud.thirdName + " is bigger than "
                           + this.firstName + " " + this.lastName + " " + this.thirdName;
                }
                if (stud.rate<this.rate)
                {
                    result =  this.firstName + " " + this.lastName + " " + this.thirdName + " is bigger than "
                               + stud.firstName + " " + stud.lastName + " " + stud.thirdName;
                }
                if (stud.rate == this.rate)
                {
                    result =  this.firstName + " " + this.lastName + " " + this.thirdName + " is equal with "
                               + stud.firstName + " " + stud.lastName + " " + stud.thirdName;
                }
            }
            return result;
 
        }
        public Subject getFavoriteSubject(){
            return this.favoriteSubject;
        }
        public void setFavoriteSubject(Subject value){
            this.favoriteSubject=value;
        }
        public String getFirstName()
        {
            String result = firstName;
            return result;
        }
        /**
         * This is getter
         * @return lastName
         */
        public String getLastName()
        {
            String result = lastName;
            return result;
        }
        /**
         * This is getter
         * @return thirdName
         */
        public String getThirdName()
        {
            String result = thirdName;
            return result;
        }
        /**
         * This is getter
         * @return age
         */
        public int getAge()
        {
            int result = age;
            return result;
        }
        public void setFirstName(String value)
        {
            firstName = value ;
        }
        /**
         * setter for lastName
         * @param value
         */
        public void setLastName(String value)
        {
            lastName = value ;
        }
        /**
         * setter for thirdName
         * @param value
         */
        public void setThirdName(String value)
        {
            thirdName = value ;
        }
        /**
         * setter for age
         * @param value
         */
        public void setAge(int value)
        {
            if ((value>18) && (value<70))
            {
                age = value ;
            
            }
            else
            {
                System.out.println(value+ " is incorrect for "+this.getClass().getCanonicalName());
            }
            
    }
        /**
         * This is getter
         * @return firstName
         */
        
        /**
         * This is getter
         * @return rate
         */
        public int getRate()
        {
            int result = rate;
            return result;
        }
        
        /**
         * setter for rate
         * @param value
         */
        public void setRate(int value)
        {
            rate = value ;
        }
        
}
SUBJECT:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public class Subject implements Cloneable {
 
    private String subjectName;
    private boolean subjectNormative;
    private int subjectDuration;
    private boolean subjectExam;
    public enum OKR {master, bachelor, spe******t};
    OKR subjectOrientation;
    public Subject()
    {
        
    }
    public Subject(String sNa, boolean sNo,int sD,boolean sE, OKR sO)
    {
        subjectName=sNa;
        subjectNormative=sNo;
        subjectDuration=sD;
        subjectExam=sE;
        subjectOrientation=sO;
    }
    @Override
    public String toString()
    {
        String rezult ="Subject[subject: " + this.subjectName+", isNormative: " + this.subjectNormative + ", hours: "+
                       this.subjectDuration + ", isExam: " + this.subjectExam + ", OKR: " + this.subjectOrientation +
                       " ]";             
        return rezult;
    }
    @Override
    public int hashCode()
    {
        int hash = this.subjectName.hashCode() + new Integer(this.subjectDuration).hashCode() + new Boolean(this.subjectExam).hashCode()
                   + new Boolean(this.subjectNormative).hashCode() + this.subjectOrientation.hashCode();
        return hash;
    }
    @Override
    public boolean equals(Object object)
    {
        boolean rezult = false;
        if (object == null)
        {
            rezult = false;
        }
        if (this == object)
        {
            rezult = true;
        }
        if (this.getClass() != object.getClass())
        {
            rezult = false;
        }
        else
        {
            Subject sub = (Subject) object;
            if (this.hashCode() == sub.hashCode())
            {
                rezult = true;
            }
        }
        return rezult;
    }
    @Override
    public Subject clone() throws CloneNotSupportedException
    {
        Subject cloneSubj=(Subject)super.clone();
        return cloneSubj;
    }
    public String compareTo(Object object)
    {
        String result = "ERROR";
        if (this.getClass() != object.getClass())
        {
            result = "ERROR";
        }
        else
        {
          Subject sub = (Subject) object;
          if (sub.subjectDuration > this.subjectDuration)
          {
              result = sub.subjectName + " is biger than " + this.subjectName;
          }
          if (sub.subjectDuration < this.subjectDuration)
          {
              result = this.subjectName + " is biger than " + sub.subjectName;
          }
          if (sub.subjectDuration == this.subjectDuration)
          {
              result = sub.subjectName + " is equal to " + this.subjectName;
          }
        }
        return result;
    }
    public String getSubjectName()
    {
        return this.subjectName;
    }
    public boolean getSubjectNormative()
    {
        return this.subjectNormative;
    }
    public int getSubjectDuration()
    {
        return this.subjectDuration;
    }
    public boolean getSubjectExam()
    {
        return this.subjectExam;
    }
    public OKR getSubjectOrientation()
    {
        return this.subjectOrientation;
    }
    public void setSubjectName(String value)
    {
        this.subjectName=value;
    }
    public void setSubjectNormative(boolean value)
    {
        this.subjectNormative = value;
    }
    public void setSubjectDuration(int value)
    {
        this.subjectDuration=value;
    }
    public void setSubjectExam(boolean value)
    {
        this.subjectExam=value;
    }
    public void setSubjectOrientation(OKR value)
    {
        this.subjectOrientation=value;
    }
    
    
}
MAIN:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package ua.edu.uabs.kontsedal.task1;
 
import ua.edu.uabs.kontsedal.task1.Subject.OKR;
 
public class Main {
 
    public static void main(String[] args) {
        Subject subject1 = new Subject ("Programming",false,144,true,OKR.master);
        Subject subject2 = new Subject ("Marketing",true,120,true,OKR.spe******t);
        Student student1 = new Student ("Kontsedal","Bohdan","Sergeevich",20, 88,subject1);
        Student student2 = new Student ("Adonay","Moisey","Iisusovich",33,72,subject2);
        System.out.println(student1.toString());
        System.out.println(student2.toString());
        System.out.println(subject1.toString());
        System.out.println(subject2.toString());
        if (student1.equals(student2))
        {
            System.out.println("Students are equals");
        }
        else
        {
            System.out.println("Students are not equals");
        }if (subject1.equals(subject2))
        {
            System.out.println("Subjects are equals");
        }
        else
        {
            System.out.println("Subjects are not equals");
        }
        System.out.println(student1.compareTo(student2));
        System.out.println(subject1.compareTo(subject2));
        Student student3 =(Student) student1.clone();
        
}
}
Добавлено через 29 минут
запихнул в try catch и все заработало =\ ..... не понимаю
0
213 / 202 / 85
Регистрация: 09.05.2012
Сообщений: 494
30.09.2013, 22:06 9
уберите throws CloneNotSupportedException с сигнатуры метода и оберните в try - catch конструкции метода clone. ваш класс поддерживает клонирование, да и еще и глубокое! о каких исключениях может идти речь?
другое дело если вы реализируете условное клонирование(когда обьекты вашего класса какбы поддерживают клонирование, но некоторые поля этого класса не поддерживают клонируование) - тут вы обязаны пропускать наружу все CloneNotSupportedException от других обьектов, которые пытаются сделать клонирование.

Добавлено через 9 минут
есть несколько категорий клонирования:
  • Поддерка клонирования. Клас реализирует интерфейс Cloneable и определяет public-метод clone(), который не предусматривает исключений(глубокое попадает сюда).
  • Условное (см. выше)
  • Поддержка клонирования, без явного декларирования этой возможности. Интерфейс Cloneable не реализируется, но при необходимости класс предоставляет protected-метод clone(), который переопределяет Object.clone().
  • Запрет клонирования. Клас не реализирует интерфейс Cloneable, но предоставляет метод clone(), который всегда выбрасывает исключение типа CloneNotSupportedException

Добавлено через 9 минут
Цитата Сообщение от edwin3d Посмотреть сообщение
Поясню свою мысль.
При вызове clone() я лично предпочитаю создавать полностью новый объект, в который, через механизм конструкторов (которые отрабатывают ВСЮ цепочку родитель<>) передаются ключевые параметры старого объекта.
конструктор копирования нужен в С++ по той причине, что там обьекты могут передаватся по значению и создаватся локальные копии обьектов. Таким образов клонирование поддерживается на уровне языка. Когда вы пишите(в с++):
C++
1
2
SomeObject so1(123);
SomeObject so2 = so1;
Компилятор вызывает конструктор копирования. И в so2 содержится копия значения обьекта so1. Аналогично при передаче обьекта по значению в метод.
Java работает с ссылками на обьекты. Потому простым присваиванием тут не обойдешься. И потому в java используется именно способ копирования через метод обьекта(тот самый clone())
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
30.09.2013, 22:07 10
Цитата Сообщение от edwin3d Посмотреть сообщение
И как мне кажется, такой метод позволяет избежать вагона трудноуловимых проблем.
Например? Метод, может быть, не самый красивый с точки зрения языка Java, но какие он может проблемы вызвать - затрудняюсь понять. К тому же, насколько я понял, использование super.clone() является общепринятым способом клонирования.
0
213 / 202 / 85
Регистрация: 09.05.2012
Сообщений: 494
30.09.2013, 22:11 11
Цитата Сообщение от edwin3d Посмотреть сообщение
И как мне кажется, такой метод позволяет избежать вагона трудноуловимых проблем.
это какие такие трудноуловимые проблемы?

Добавлено через 1 минуту
вот блин. не успел.
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
30.09.2013, 22:13 12
Цитата Сообщение от lowercase Посмотреть сообщение
Java работает с сылками на обьекты. Потому простым присваиванием тут не обойдешься. И потому в java используется именно способ копирования через метод обьекта.
Он имеет в виду, что он делает так:

Java
1
2
3
4
5
6
7
s1 = new MyClass();
<...>
s2 = new MyClass();
s2.field1 = s1.field1;
s2.field2 = s1.field2;
<...>
s2.fieldN = s1.fieldN;
0
91 / 91 / 10
Регистрация: 18.05.2013
Сообщений: 265
01.10.2013, 09:09 13
Вы видимо так и не поняли о чем я толкую.
Так вот, я лично считаю, что конструктор копирования необходим и в Java, именно потому, что работает она со ссылками и необходимо обеспечить передачу по значению.
И для этого я делаю специальный ПРИВАТНЫЙ конструктор, который создает новый объект, т.е. грубо говоря как раз и описываю тот самый конструктор копирования.

Делается это так (самый примитивный пример, на практике все намного сложнее, фактически реализуется полноценная фабрика со своей логикой):

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Test implements Cloneable 
{
    private int i;
    Test()
    {
        this.i = 0;
    }
    private Test(int i)
    {
        this.i = i;
    }
    @Override 
    public Test clone()
    {
        return new Test(this.i);
    }
}
Теперь почему я делаю именно так.
При разработке многопоточных приложений несколько раз раз нарывался на ситуации, когда родительский класс, при clone устраивал передачу по ссылкам содержимого своих структур.
Что не удивительно и правильно, потому как коллекции по clone() содержимое сохраняется.
И теперь внимание - почувствуйте разницу - переписывать clone в super классе (это если это допустимо) + следить на ним или же сделать один конструктор.
Но есть и более худшие ситуации - когда речь идет о абстрактных классах, которые содержат некие структуры, типа коллекций ... тут без этой схемы никак и никуда.
Без моей схемы - беда будет
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
01.10.2013, 17:12 14
edwin3d, а зачем тогда вообще Cloneable и clone? Если вы сделали копирующий конструктор - так сделайте его публичным, пусть клиент пользует конструктором. Мне кажется, раз уж вы сделали clone, так надо по-честному ломиться в Object.clone(). А то получается вы в API говорите, что я сделаю клон, а на самом деле втихаря вызываете конструктор или фабрику.
0
91 / 91 / 10
Регистрация: 18.05.2013
Сообщений: 265
01.10.2013, 17:52 15
http://docs.oracle.com/javase/... lone%28%29

"
Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression:

Java
1
   x.clone() != x
will be true, and that the expression:

Java
1
      x.clone().getClass() == x.getClass()
will be true, but these are not absolute requirements. While it is typically the case that:

Java
1
      x.clone().equals(x)
will be true, this is not an absolute requirement.
"
Эти условия я выполняю, не нарушая API.

Читаем дальше:
"
By convention, the object returned by this method should be independent of this object (which is being cloned). To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it.
"
Итого - super.clone только один из путей решения.
Нет ли запретов, не рекомендаций не делать иначе и т.д.
Есть только - типа для достижения это цели Вы можете идти так.

Добавлено через 8 минут
А теперь сравните задачу сложности сопровождения кода для сложных объектов, где выстраиваете цепочку clone, увязывая это с данными, полями и т.д. и задачей сопровождения все того-же конструктора для класса, который есть единая точка создания объекта при тех или иных раскладах и т.д.
0
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
01.10.2013, 18:07 16
Цитата Сообщение от edwin3d Посмотреть сообщение
By convention, the object returned by this method should be independent of this object (which is being cloned). To achieve this independence, it may be necessary to modify one or more fields of the object returned by super.clone before returning it.
"
Итого - super.clone только один из путей решения.
Вы извращаете смысл фразы. "may be necessary" относится к "to modify", а не к "by super.clone".

А эту часть вы по какой-то причине решили не цитировать:
By convention, the returned object should be obtained by calling super.clone.
В книге "Effective Java" Блох говорит строже:
No constructors are called.
А трудности с использованием коприующего конструктора у вас возникают потому, что вы неправильно используете шаблон:

Java
1
2
3
4
5
6
7
8
9
10
11
12
public class Test
{
    private int i;
    Test()
    {
        this.i = 0;
    }
    public Test(Test t)
    {
        this.i = t.i;
    }
}
0
2586 / 2259 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
01.10.2013, 18:13 17
я покажу всю суть проблемы на простом примере
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
 
/**
 * @author mutagen
 */
public class SimpleCloneableProblem implements Cloneable {
 
    private List<Integer> li;
 
    public SimpleCloneableProblem(List<Integer> li) {
        this.li = li;
    }
 
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 29 * hash + Objects.hashCode(this.li);
        return hash;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SimpleCloneableProblem other = (SimpleCloneableProblem) obj;
        if (!Objects.equals(this.li, other.li)) {
            return false;
        }
        return true;
    }
 
    public SimpleCloneableProblem myClone(SimpleCloneableProblem s) {
        ArrayList<Integer> al = new ArrayList<>();
        al.addAll(s.li);
        return new SimpleCloneableProblem(al);
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone(); //To change body of generated methods, choose Tools | Templates.
    }
 
    @Override
    public String toString() {
        return "SimpleCloneableProblem{" + "li=" + li + '}';
    }
 
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws CloneNotSupportedException {
        List<Integer> l = new ArrayList<Integer>() {
            {
                add(1);
                add(2);
                add(3);
            }
        };
        SimpleCloneableProblem sc = new SimpleCloneableProblem(l);
        SimpleCloneableProblem scBad = (SimpleCloneableProblem) sc.clone();
        SimpleCloneableProblem scOK = sc.myClone(sc);
        System.out.println(sc.equals(scBad));
        System.out.println(scBad.equals(sc));
        System.out.println(sc.equals(scOK));
        System.out.println(scBad.equals(scOK));
        System.out.println("Now add 10 to list");
        l.add(10);
//        Изменили модифабельный объект и вот у нас уже проблема
        System.out.println(sc.equals(scBad));
        System.out.println(scBad.equals(sc));
        System.out.println(sc.equals(scOK));
        System.out.println(scBad.equals(scOK));
        System.out.println(sc);
        System.out.println(scBad);
        System.out.println(scOK);
    }
}
Bash
1
2
3
4
5
6
7
8
9
10
11
12
true
true
true
true
Now add 10 to list
true
true
false
false
SimpleCloneableProblem{li=[1, 2, 3, 10]}
SimpleCloneableProblem{li=[1, 2, 3, 10]}
SimpleCloneableProblem{li=[1, 2, 3]}
1
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
01.10.2013, 18:16 18
Цитата Сообщение от mutagen Посмотреть сообщение
я покажу всю суть проблемы на простом примере
Дык понятно, что любая ссылка на изменяемый объект должна быть заменена ссылкой на клона. Суть вопроса в том, можно ли нарушить конвенцию и реализовать clone с помощью конструктора или фабрики.
0
2586 / 2259 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
01.10.2013, 18:19 19
Цитата Сообщение от Gibby Посмотреть сообщение
Суть вопроса в том, можно ли нарушить конвенцию и реализовать clone с помощью конструктора или фабрики.
суть клона в том что он идентичен, но независим, способ по конвенции создаёт зависимый инстанс, его можно применять только если все поля класса иммутабельны.

это всё та же проблема deepCopy из массивов, решать её лучше копирующим конструктором, так как в таком случае это вас автоматически спасает от кучи проблем с наследованием и других
1
154 / 154 / 10
Регистрация: 16.10.2012
Сообщений: 354
Записей в блоге: 1
01.10.2013, 18:23 20
Проблема конструктора или фабрики на самом деле вот в этом:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Foo implements Cloneable {
    private int i;
    Foo()
    {
        this.i = 0;
    }
    private Foo(int i)
    {
        this.i = i;
    }
    @Override 
    public Foo clone()
    {
        return new Foo(this.i);
    }
}
 
 
class Bar  extends Foo implements Cloneable {
    @Override
    public Bar clone() {
        return (Bar)super.clone();
    }
}
 
class Main {
    public static void main(String[] args) {
        Bar t1 = new Bar();
        Bar t2 = t1.clone();
        System.out.println(t1);
        System.out.println(t2);
    }
}

Запуская в Bar super.clone мы рассчитывали, что он создаст нам экземпляр Bar. А он создал нам экземляр Foo. И мы схватили волшебный ClassCastException на ровном месте.
0
01.10.2013, 18:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.10.2013, 18:23
Помогаю со студенческими работами здесь

Метод Range.Find выдает ошибку
Всем привет! Такая вот занятная штука. Хотел использовать Find, чтобы найти фрагмент формулы. Как...

Метод вычисляющий значения выдает ошибку компиляции
Добрый день возникла проблема.Выдаёт ошибку при компиляции,вроде всё правильно делал. using...

Метод Paste (Excel, OLE) иногда выдает ошибку
Доброго дня. Делаю вставку из одного файла EXCEL в другой с помощью OLE. Проверяю работу программы...

Выдает ошибку, что метод getPreventDefault является устаревшим
Доброго времени суток ругается Метод getPreventDefault() является устаревшим. Для его замены...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru