Groovy Documentation

## groovy.transform
[Java] Annotation Type AutoClone

    java.lang.Object
      groovy.transform.AutoClone

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoCloneASTTransformation")
    public @interface AutoClone

Note: This annotation is currently experimental! Use at your own risk!

Class annotation used to assist in the creation of `Cloneable` classes. The `@AutoClone` annotation instructs the compiler to execute an AST transformation which adds a public `clone()` method and adds `Cloneable` to the interfaces which the class implements.

Because the JVM doesn't have a one-size fits all cloning strategy, several customizations exist for the cloning implementation. By default, the `clone()` method will call `super.clone()` before calling `clone()` on each `Cloneable` property of the class.

Example usage:

     import groovy.transform.AutoClone
     @AutoClone
     class Person {
       String first, last
       List favItems
       Date since
     }

Which will create a class of the following form:

     class Person implements Cloneable {
       ...
       public Object clone() throws CloneNotSupportedException {
         Object result = super.clone()
         result.favItems = favItems.clone()
         result.since = since.clone()
         return result
       }
       ...
     }

Which can be used as follows:

     def p = new Person(first:'John', last:'Smith', favItems:['ipod', 'shiraz'], since:new Date())
     def p2 = p.clone()

     assert p instanceof Cloneable
     assert p.favItems instanceof Cloneable
     assert p.since instanceof Cloneable
     assert !(p.first instanceof Cloneable)

     assert !p.is(p2)
     assert !p.favItems.is(p2.favItems)
     assert !p.since.is(p2.since)
     assert p.first.is(p2.first)

In the above example, `super.clone()` is called which in this case calls `clone()` from `java.lang.Object`. This does a bit-wise copy of all the properties (references and primitive values). Properties like `first` has type `String` which is not `Cloneable` so it is left as the bit-wise copy. Both `Date` and `ArrayList` are `Cloneable` so the `clone()` method on each of those properties will be called. For the list, a shallow copy is made during its `clone()` method.

If your classes require deep cloning, it is up to you to provide the appropriate deep cloning logic in the respective `clone()` method for your class.

If one of your properties contains an object that doesn't support cloning or attempts deep copying of a data structure containing an object that doesn't support cloning, then a `CloneNotSupportedException` may occur at runtime.

Another popular cloning strategy is known as the copy constructor pattern. If any of your fields are `final` and `Cloneable` you should set `style=COPY_CONSTRUCTOR` which will then use the copy constructor pattern. Here is an example making use of the copy constructor pattern:

     import groovy.transform.AutoClone
     import static groovy.transform.AutoCloneStyle.*
     @AutoClone(style=COPY_CONSTRUCTOR)
     class Person {
       final String first, last
       final Date birthday
     }
     @AutoClone(style=COPY_CONSTRUCTOR)
     class Customer extends Person {
       final int numPurchases
       final List favItems
     }

Which will create classes of the following form:

     class Person implements Cloneable {
       ...
       protected Person(Person other) throws CloneNotSupportedException {
         first = other.first
         last = other.last
         birthday = other.birthday.clone()
       }
       public Object clone() throws CloneNotSupportedException {
         return new Person(this)
       }
       ...
     }
     class Customer extends Person {
       ...
       protected Customer(Customer other) throws CloneNotSupportedException {
         super(other)
         numPurchases = other.numPurchases
         favItems = other.favItems.clone()
       }
       public Object clone() throws CloneNotSupportedException {
         return new Customer(this)
       }
       ...
     }

If you use this style on a child class, the parent class must also have a copy constructor (created using this annotation or by hand). This approach can be slightly slower than the traditional cloning approach but the `Cloneable` fields of your class can be final.

As a final example, if your class already implements the `Serializable` or `Externalizable` interface, you can choose the following cloning style:

     @AutoClone(style=SERIALIZATION)
     class Person implements Serializable {
       String first, last
       Date birthday
     }

which outputs a class with the following form:

     class Person implements Cloneable, Serializable {
       ...
       Object clone() throws CloneNotSupportedException {
         def baos = new ByteArrayOutputStream()
         baos.withObjectOutputStream{ it.writeObject(this) }
         def bais = new ByteArrayInputStream(baos.toByteArray())
         bais.withObjectInputStream(getClass().classLoader){ it.readObject() }
       }
       ...
     }

This will output an error if your class doesn't implement one of `Serializable` or `Externalizable`, will typically be significantly slower than the other approaches, also doesn't allow fields to be final, will take up more memory as even immutable classes like String will be cloned but does have the advantage that it performs deep cloning automatically.

Further references on cloning:

- http://www.codeguru.com/java/tij/tij0128.shtml
- http://www.artima.com/objectsandjava/webuscript/ClonCollInner1.html
- http://courses.dce.harvard.edu/~cscie160/JDCTipsCloning
- http://www.agiledeveloper.com/articles/cloning072002.htm

Authors:
  Paul King

See Also:
  AutoCloneStyle
  AutoExternalize

Since:
  1.8.0

Optional Element Summary
`java.lang.String[]` | `excludes` Comma separated list of property names to exclude from cloning.
`boolean` | `includeFields` Include fields as well as properties when cloning.
`AutoCloneStyle` | `style` Style to use when cloning.

Method Summary

Methods inherited from class java.lang.Object
java.lang.Object#wait(long), java.lang.Object#wait(long, int), java.lang.Object#wait(), java.lang.Object#equals(java.lang.Object), java.lang.Object#toString(), java.lang.Object#hashCode(), java.lang.Object#getClass(), java.lang.Object#notify(), java.lang.Object#notifyAll()

Element Detail

### excludes

    public java.lang.String[] excludes

  Comma separated list of property names to exclude from cloning. For convenience, a String with comma separated names can be used in addition to an array (using Groovy's literal list notation) of String values. @default {}

### includeFields

    public boolean includeFields

  Include fields as well as properties when cloning. @default false

### style

    public AutoCloneStyle style

  Style to use when cloning. @default AutoCloneStyle.CLONE

Groovy Documentation