Elettracompany.com

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Интерфейс cloneable java

Java Cloneable interface – Is it broken?

By Lokesh Gupta | Filed Under: Java Cloning

In a Java application, even if a class implements Cloneable interface, we can not make a clone of the class. This itself says a lot about broken behavior of cloning in Java. In this post, I will explore other reasons for saying so.

In cloning in Java, we discussed the various ways of creating clone of Java objects including shallow and deep cloning, copy constructors and some best practices. Now let’s discuss about Cloneable interace gaps.

How Java Cloneable interface is braken?

  1. The very first gap is that clone() method should have been in Cloneable interface. If you implement Cloneable interface(don’t override clone() method) then it does not affect a single thing in your class on runtime. In fact, the default behavior should have been if Class A implements Cloneable then someone should be able to do this:
  2. clone() method does not call any constructor for creating the new instance, which makes it another variant of constructor with behavior not in our control. In other words: “Cloning invokes an extralinguistic way of constructing objects – i.e. without constructors“.
  3. Apart from above facts, it is also a classic example of spelling mistakes. The correct spelling should have been “Clonable“.
  4. There is no mechanism in java to create deep copies. Even calling super.clone() till the Object class, creates shallow copy.

What experts say about Java Cloneable interface

Josh Block in an interview

“There are a few design flaws, the biggest of which is that the Cloneable interface does not have a clone method. And that means it simply doesn’t work: making something Cloneable doesn’t say anything about what you can do with it. Instead, it says something about what it can do internally. It says that if by calling super.clone repeatedly it ends up calling Object’s clone method, this method will return a field copy of the original.”

Ken Arnold in an inteview

“If I were to be God at this point, and many people are probably glad I am not, I would say deprecate Cloneable and have a Copyable, because Cloneable has problems. Besides the fact that it’s misspelled, Cloneable doesn’t contain the clone method. That means you can’t test if something is an instance of Cloneable, cast it to Cloneable, and invoke clone. You have to use reflection again, which is awful. That is only one problem, but one I’d certainly solve.”

Java copy best practices

As discussed in my previous post, use factory methods when you need to have a copy of an object. It has following benefits:

  1. You can return an instance of different class also if needed. For example, If someone wants to copy a LinkedList , if needed you can return an ArrayList also.
  2. You can choose whether you need to make deep or shallow copy.
  3. You can decide which members needs to be copied and which not.
  4. Different methods can have different names clearly pointing their responsibilities.

I hope this post shed some light on broken behavior of Java Cloneable interface (marker interface) and best practices while creating copy of an Object in Java.

Clone () метод в Java

Клонирование объекта относится к созданию точной копии объекта. Он создает новый экземпляр класса текущего объекта и инициализирует все его поля точно содержимым соответствующих полей этого объекта.

Использование оператора присваивания для создания копии ссылочной переменной
В Java нет оператора для создания копии объекта. В отличие от C ++, в Java, если мы используем оператор присваивания, он создаст копию ссылочной переменной, а не объекта. Это можно объяснить на примере. Следующая программа демонстрирует то же самое.

// Java-программа для демонстрации этого назначения
// оператор только создает новую ссылку на то же
// объект.

// Тестовый класс, чьи объекты клонированы

public static void main(String[] args)

Test ob1 = new Test();

// Создание новой ссылочной переменной ob2

// указываем на тот же адрес, что и ob1

// Любые изменения, сделанные в ob2, будут отражены

Выход:

Создание копии с использованием метода clone ()

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

  • Каждый класс, который реализует clone (), должен вызывать super.clone () для получения ссылки на клонированный объект.
  • Класс также должен реализовывать интерфейс java.lang.Cloneable, чей объект-клон мы хотим создать, в противном случае он вызовет исключение CloneNotSupportedException при вызове метода clone для объекта этого класса.
  • Синтаксис:

Использование метода clone () -Shallow Copy

// Java-программа для демонстрации мелкой копии
// используя clone ()

// Ссылка на объект этого класса
// содержится в Test2

// Содержит ссылку на Test и реализует
// клон с мелкой копией.

class Test2 implements Cloneable

Test c = new Test();

public Object clone() throws

return super .clone();

public class Main

public static void main(String args[]) throws

Test2 t1 = new Test2();

Test2 t2 = (Test2)t1.clone();

// Создание копии объекта t1 и передача

// Изменять примитивный тип t2 не буду

// отражаться в поле t1

// Изменение в поле типа объекта будет

// отражается как в t2, так и в t1 (мелкая копия)

Выход:

В приведенном выше примере t1.clone возвращает поверхностную копию объекта t1. Для получения глубокой копии объекта необходимо выполнить определенные модификации в методе клонирования после получения копии.

Читать еще:  Java sql time

Глубокая копия против мелкой копии

  • Мелкая копия — это метод копирования объекта, который по умолчанию используется при клонировании. В этом методе поля старого объекта X копируются в новый объект Y. При копировании поля типа объекта ссылка копируется в Y, т. Е. Объект Y будет указывать на то же местоположение, на которое указывает X. Если значение поля является тип примитива копирует значение типа примитива.
  • Поэтому любые изменения, сделанные в ссылочных объектах в объекте X или Y, будут отражены в другом объекте.

Мелкие копии дешевы и просты в изготовлении. В приведенном выше примере мы создали мелкую копию объекта.

Использование метода clone () — Deep Copy

  • Если мы хотим создать глубокую копию объекта X и поместить ее в новый объект Y, то создается новая копия любых полей объектов, на которые есть ссылки, и эти ссылки помещаются в объект Y. Это означает, что любые изменения, сделанные в полях объекта, на которые есть ссылки, в объекте X или Y будет отражаться только в этом объекте, а не в другом. В приведенном ниже примере мы создаем глубокую копию объекта.
  • Глубокая копия копирует все поля и создает копии динамически распределенной памяти, на которую указывают поля. Глубокое копирование происходит, когда объект копируется вместе с объектами, на которые он ссылается.

// Java-программа для демонстрации глубокой копии
// используя clone ()

// Ссылка на объект этого класса
// содержится в Test2

// Содержит ссылку на Test и реализует
// клон с глубокой копией.

class Test2 implements Cloneable

Test c = new Test();

public Object clone() throws

// Назначаем мелкую копию новой ссылочной переменной t

Test2 t = (Test2) super .clone();

// Создать новый объект для поля c

// и назначить его полученной копии,

// сделать глубокую копию

public class Main

public static void main(String args[]) throws

Test2 t1 = new Test2();

Test2 t3 = (Test2)t1.clone();

// Изменять примитивный тип t2 не буду

// отражаться в поле t1

// Изменения в поле типа объекта t2 не будет

// отражаться в t1 (глубокая копия)

Выход:

В приведенном выше примере мы видим, что для объекта-копии был назначен новый объект класса Test, который будет возвращен в методе clone. Благодаря этому t3 получит глубокую копию объекта t1. Таким образом, любые изменения, сделанные в полях объекта ‘c’ к t3, не будут отражены в t1.

Преимущества метода клонирования:

  • Если мы используем оператор присваивания для назначения ссылки на объект другой ссылочной переменной, то это будет указывать на то же адресное местоположение старого объекта, и новая копия объекта не будет создана. В связи с этим любые изменения в ссылочной переменной будут отражены в исходном объекте.
  • Если мы используем конструктор копирования, то мы должны явно скопировать все данные, т.е. мы должны явно переназначить все поля класса в конструкторе. Но в методе клонирования эта работа по созданию новой копии выполняется самим методом. Чтобы избежать дополнительной обработки, мы используем клонирование объектов.

Эта статья предоставлена Анкит Агарвал. Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью и отправить ее по почте на contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

How to implement cloning in java using Cloneable interface?

The java cloning mechanism is used when we need exact copy of an object. In this article, we will discuss and explore most of the important aspects of java cloning.

Introduction:

The Cloneable interface in java is a marker interface. It does have any method. But if we write a class as below, it gives a message to the jvm that the class can be cloned. The following code shows a simple object cloning process.

The Cloneable interface does not have any members. The interface is used to indicate that a class (which implements the interface) allows a bitwise copy of an object, known as cloning. An exception known as ‘CloneNotSupportedException’ is thrown if clone () is called on a class which does not implement Cloneable interface. In a cloning process the constructor of the object is not called. So cloning can be defined as an exact copy of the original object.

Listing 1: Sample class implements Cloneable interface

Listing 2: Sample class showing cloning of objects

In the above example, the method getClone calls the clone method in the object and returns the object. It must be noticed here that the object with is returned after the cloning mechanism has to be type casted into its appropriate type, in this case it is CloneClass

If the class is not implementing the cloneable interface, and we try to clone that object we get a CloneNotSupportedException . In the process of cloning, the constructor is not called rather an exact copy of the said object is created. But the object of which the clone is created, must implement the cloneable interface.

The class Object’s clone () method creates and returns a copy of the object, with the same class and with all the fields having the same values. However, Object.clone () throws a CloneNotSupportedException unless the object is an instance of a class that implements the marker interface Cloneable.

The default implementation of Object.clone () performs a shallow copy. If a class requires a deep copy or some other custom behavior, it must have its customized clone () method after they obtain the copy from the super class.

Читать еще:  Java security nosuchalgorithmexception

Advantages of cloning:

Cloning mechanism saves extra task of the developer in case we need to create a copy of an object. We do not need to call the new operator of the object. Thus cloning saves a lot of extra processing tasks of developer. A clone of an object is an exact copy of the object.

Disadvantages of cloning:

One disadvantage of cloning is that the return type of the clone method is an Object. Hence a type casting is required on the created object.

Another disadvantage is that it is not possible to access the clone method on an abstract type. Most interfaces and abstract classes in Java do not have to specify a public clone method. As a result, the clone method is used only if the actual class of an object is known which is against the abstraction principle of using the most generic type possible. For example, if one has a List reference in Java, one cannot invoke clone method on that reference because List specifies no public clone () method. Actual implementations of List like ArrayList and LinkedList all generally have clone () methods themselves, but it is inconvenient and bad abstraction to carry around the actual class type of an object.

Cloning is a potentially dangerous action, as it can have some unintended side effects. e.g., if the object being cloned contains a reference variable say refObject, then in the cloned object, refObject will have the reference of the same object which the original object is referring to. If the clone makes a change in the contents of the refObject, then the change will be reflected in the original object as well. Consider the following example — If an object opens an I/O stream and is then cloned, then both of the two objects will be capable of operating on the same stream. Further, if one of these objects closes the stream, then the stream is closed for both and if the second object tries to write to it, this causes an error.

Since cloning can cause some problems, the clone method. So the clone method should be called from within a class which is implementing the cloneable interface where the method calling the clone method is made protected, or it must be explicitly overridden by the class which is public. In the example above we have seen cloning by making the clone protected. The following example illustrates the cloning methodology via overriding:

Listing 3: Sample class implements Cloneable interface

Listing 4: Sample class implements cloning using method overriding

In this example the method, the method clone of the object class is overridden that is why it is declared public in contrast to the earlier example, where the getClone does not have any access modifiers making it accessible only at the package level.

In either of these two approaches, implementing the cloneable interface is mandatory.

The side effects caused by cloning are sometimes difficult to identify in the initial level. It is easy to think that a class is safe for cloning when it actually is not. In general, is not advised to implement the Cloneable interface for any class without having a solid business ground.

Alternative to cloning:

Cloning mechanism has few alternatives:

  • Copy constructor — a copy constructor is a constructor which accepts another instance of the same class as a parameter.
  • Factory method — these methods are not always adequate when the concrete type of the cloned object is not known in advance.
  • Use of serialization and deserialization is another alternative to using clone.

Как скопировать объект в Java?

660 Veera [2009-05-15 17:30:00]

Рассмотрим следующий код:

Итак, я хочу скопировать dum на dumtwo и изменить dum не затрагивая dumtwo . Но вышеприведенный код не делает этого. Когда я что-то меняю в dum , то такое же изменение происходит и в dumtwo .

Я думаю, когда я говорю dumtwo = dum , Java копирует только ссылку. Итак, есть ли способ создать новую копию dum и присвоить ей dumtwo ?

java object clone copy

21 ответ

535 Решение egaga [2009-05-15 17:35:00]

Создайте конструктор копирования:

Каждый объект имеет также метод клонирования, который можно использовать для копирования объекта, но не использовать его. Слишком легко создать класс и сделать неправильный метод клонирования. Если вы собираетесь это сделать, прочитайте, по крайней мере, то, что Джошуа Блох должен сказать об этом в Эффективная Java.

Основные: Копирование объектов на Java.

Предположим, что объект- obj1 , содержащий два объекта, содержит Obj1 и , содержащий Obj2.

мелкое копирование:
мелкое копирование создает новый instance того же класса и копирует все поля в новый экземпляр и возвращает его. Класс объекта предоставляет метод clone и обеспечивает поддержку мелкого копирования.

Глубокое копирование:
Глубокая копия возникает, когда объект копируется вместе с объектами, к которым он относится. Ниже изображения отображается obj1 после того, как на нем была выполнена глубокая копия. Скопировано не только obj1 , но и объекты, содержащиеся в нем, были скопированы. Мы можем использовать Java Object Serialization , чтобы сделать глубокую копию. К сожалению, этот подход также имеет некоторые проблемы (подробные примеры).

Возможные проблемы:
clone сложно реализовать правильно.
Лучше использовать Оборонительное копирование, конструкторы копирования (как @egaga reply) или статические методы factory.

  • Если у вас есть объект, который, как вы знаете, имеет общедоступный метод clone() , но вы не знаете тип объекта во время компиляции, тогда у вас есть проблема. Java имеет интерфейс под названием Cloneable . На практике мы должны реализовать этот интерфейс, если хотим создать объект Cloneable . Object.clone защищен, поэтому мы должны переопределить его общедоступным методом, чтобы он был доступен.
  • Другая проблема возникает, когда мы пытаемся выполнить глубокое копирование сложного объекта. Предположим, что метод clone() всех переменных-членов-членов также делает глубокую копию, это слишком рискованно из предположения. Вы должны контролировать код во всех классах.

Например org.apache.commons.lang.SerializationUtils будет иметь метод для Deep clone с использованием сериализации (Source). Если нам нужно клонировать Bean, тогда в org.apache.commons.beanutils есть несколько методов утилиты (Источник).

  • cloneBean будет клонировать Bean на основе доступных свойств getters и seters, даже если сам класс Bean не реализует Cloneable.
  • copyProperties скопирует значения свойств из источника Bean в пункт назначения Bean для всех случаев, когда имена свойств совпадают.

Обязательный интерфейс Cloneable в Java

У меня есть небольшая проблема в Java. У меня есть интерфейс под названием Modifiable. Объекты, реализующие этот интерфейс, могут быть изменены.

У меня также есть класс ModifyCommand (с шаблоном команд), который получает два изменяемых объекта (чтобы поменять их местами в списке дальше — это не мой вопрос, я уже разработал это решение).

Класс ModifyCommand начинается с создания клонов изменяемых объектов. Логично, что я сделал свой модифицируемый интерфейс расширяющимся клонируемым. Затем интерфейс определяет метод clone(),который его реализующие классы должны переопределить.

Затем, в ModifyCommand году, я могу сделать: firstModifiableObject.clone(). Моя логика заключается в том, что классы, реализующие Modifiable, должны будут переопределить метод clone из Object, поскольку они будут клонироваться (это то, что я хочу сделать).

Дело в том, что когда я определяю классы, реализующие Modifiable, и я хочу переопределить clone(), он не позволит мне, заявив, что метод clone() из класса объектов скрывает тот, который от Modifiable.

Что же мне делать? У меня сложилось впечатление, что «I’m doing it wrong».

Edit: он думает, что я забуду clone() вещь. Я либо а) предположу, что объект, переданный Модифицируемому объекту (реализующему интерфейс), уже клонирован, либо б) сделаю другой метод, называемый, например, copy(), который в основном будет делать глубокую копию модифицируемого объекта (или, возможно, универсальное решение будет работать. ).

6 Ответов

Если вы используете java 1.5 или выше, вы можете получить желаемое поведение и удалить приведение таким образом:

Поскольку Foo расширяет объект, это все еще удовлетворяет исходному контракту класса объектов. Код, который не уточняет метод clone() правильно, не будет компилироваться из-за дополнительных ограничений, накладываемых модифицируемым интерфейсом. В качестве бонуса вызывающий код не должен приводить к результату метода clone.

Добавляя к ответу Шона Рейли, это должно решить вашу проблему и является более типобезопасным. Он компилируется и отлично работает со мной на JDK6:

Я не мог протестировать его с Java 5, потому что у меня его нет, но я думаю, что он будет работать нормально.

Вы не должны переопределить метод clone на интерфейс, который можно изменять.

Я понимаю, что вы пытаетесь заставить всех переопределить clone method(), но вы не можете этого сделать.

Другими словами, вы не можете переопределить класс в интерфейсе:

Метод clone() всегда связан с Object.class, а не с клонируемым интерфейсом. Вы просто можете переопределить его на другом объекте, а не в интерфейсе.

публичный класс CloningExample реализует Cloneable <

Вы определили сигнатуру точно так же, как она есть в объекте?

Это должно компилировать-добавить пользовательский код в тело. Википедия была удивительно полезна в этом вопросе.

Как выглядит ваша сигнатура метода для вашего метода клонирования? Чтобы он соответствовал Клонируемому интерфейсу, он должен был бы вернуть объект. Если вы объявляете его как возвращающий модифицируемый, то это может быть проблемой.

Похожие вопросы:

для клонирования объекта мне нужно реализовать интерфейс ‘cloneable’. потому что здесь мой класс-это файл jar(я имею в виду API). так что я не могу редактировать класс. я слышал, что все классы.

Из документации Object#clone() : Обратите внимание, что все массивы считаются реализующими интерфейс Cloneable . В противном случае этот метод создает новый экземпляр класса этого объекта и.

Cloneable в Java изначально нарушено. В частности, моя самая большая проблема с интерфейсом заключается в том, что он ожидает поведение метода, которое не определяет сам метод. Поэтому при переходе.

Я не уверен, как реализовать интерфейс Cloneable в моем сложном классе. Я реализовал сопоставимый, но я просто не могу понять, как клонировать. У меня есть следующий пример кода,который я использую.

Например, мы пишем класс XXX для реализации Cloneable, и мы переопределяем метод clone в классе XXX, необходимо ли вызывать super.clone в методе?

Я пытаюсь создать cloneable интерфейс и сталкиваюсь с некоторыми проблемами получения структур для реализации интерфейса. Похоже, это предел go, которого нет во многих других языках. Я пытаюсь.

У меня есть класс, объект которого я хочу клонировать. Я сделал это, реализовав Cloneable интерфейс и переопределив метод clone. Но если я создаю метод клонирования, не реализуя интерфейс Cloneable.

Если вы реализуете интерфейс компилятор просит вас предоставить реализацию этих методов. Но в случае вызова переопределенного метода clone() как компилятор узнает, что конкретный интерфейс не.

Я хочу реализовать cloneable интерфейс, но я не могу. Я использую J2me, это дает мне ошибку создайте интерфейс Cloneable в вашем пакете. Насколько я знаю, J2me позволяет реализовать Cloneable.

Ссылка на основную публикацию
Adblock
detector