There are two popular approaches.  One is to provide a clone method as you mentioned, like so.
public class C implements Cloneable {
    @Override public C clone() {
        try {
            final C result = (C) super.clone();
            // copy fields that need to be copied here!
            return result;
        } catch (final CloneNotSupportedException ex) {
            throw new AssertionError();
        }
}
Pay attention to the "copy fields ... here!" part.  The initial result is only a shallow copy, meaning that if there's a reference to an object, both the original and result will share the same object.  For example, if C contains private int[] data you'd probably want to copy that.
...
final C result = (C) super.clone();
result.data = data.clone();
return result;
...
Note that you don't need to copy primitive fields, as their content is already copied, or immutable objects, as they can't change anyways.
The second approach is to provide a copy constructor.
public class C {
    public C(final C c) {
        // initialize this with c
    }
}
Or a copy factory.
public class C {
    public static C newInstance(final C c) {
        return new C(c);
    }
    private C(final C c) {
        // initialize this with c
    }
}
Both approaches have their respective properties.  clone is nice because its a method, so you don't have to know the exact type.  In the end, you should always end up with a "perfect" copy.  The copy constructor is nice because the caller has a chance to decide, as can be seen by the Java Collections.
final List c = ... 
// Got c from somewhere else, could be anything.
// Maybe too slow for what we're trying to do?
final List myC = new ArrayList(c);
// myC is an ArrayList, with known properties
I recommend choosing either approach, whichever suits you better.
I'd use the other approaches, like reflective copying or immediate serializing/deserializing, in unit tests only.  To me, they feel less appropriate for production code, mainly because of performance concerns.