我试图理解java中clone()方法下面发生了什么,我想知道如何做一个新的调用
public class Person implements Cloneable {
private String firstName;
private int id;
private String lastName;
//constructors, getters and setters
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
return p;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的克隆代码我想知道底下发生了什么,以及新呼叫之间有什么区别因为.
这是我的客户端代码
Person p = new Person("John", 1, "Doe");
Person p2 = null;
try {
p2 = (Person) p.clone();
} catch (CloneNotSupportedException ex) {
Logger.getLogger(clientPrototype.class.getName()).log(Level.SEVERE, null, ex);
}
p2.setFirstName("Jesus");
System.out.println(p);
System.out.println(p2);
Run Code Online (Sandbox Code Playgroud) 我正在维护一个较旧的Java代码库(jvm 1.4),它似乎使用克隆作为对象实例化的替代方案,我猜测它是一种性能优化.这是一个人为的例子:
public class Foo {
private SomeObject obj; // SomeObject implements Cloneable
public Foo() {
obj = new SomeObject();
obj.setField1("abc"); // these fields will have the same value every time
obj.setField2("def");
}
public void doStuff() {
SomeObject newObj = obj.clone(); // clone it instead of using a factory method
// do stuff with newObj
}
}
Run Code Online (Sandbox Code Playgroud)
关于过早优化的常见警告尽管如此,这实际上是一个推荐的成语吗?
如果Java类实现了Serializable接口但没有公共clone()方法,通常可以创建如下的深层副本:
class CloneHelper {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
byte[] bytes = baos.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
T copy = (T) ois.readObject();
ois.close();
return copy;
} catch (ClassNotFoundException ex) {
// Shouldn't happen
throw new Error(ex);
} catch (IOException ex) {
// Probably a bug in T's custom serialization methods
throw …Run Code Online (Sandbox Code Playgroud) 我有一些代码使用Object.clone执行深层复制,但我正在尝试使用更"可接受"的复制构造函数重写它.下面是我正在尝试做的两个简单示例,第一个使用克隆,第二个使用复制构造函数.
使用克隆的深层复制
import java.util.*;
abstract class Person implements Cloneable {
String name;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Teacher extends Person implements Cloneable {
int courses;
public String toString() { return name + ": courses=" + courses; }
}
class Student extends Person implements Cloneable {
double gpa;
public String toString() { return name + ": gpa=" + gpa; }
}
public class DeepCopy_Clone {
private static List<Person> deepCopy(List<Person> people) throws CloneNotSupportedException {
List<Person> copy …Run Code Online (Sandbox Code Playgroud) 代码背后:
class A implements Cloneable
{
int i, j;
A(int i, int j)
{
this.i = i;
this.j = j;
}
A()
{
}
}
class B extends A
{
int l, m;
B()
{
}
B(int l, int m)
{
this.l = l;
this.m = m;
}
public static void main(String l[])
{
A obj = new A(1, 2);
B obj1 = (B) obj.clone(); // ERROR
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我违反了克隆的含义,因为我试图将一个对象的字段分配给一个完全不同的对象.但它的错误陈述使我感到困惑.
声明:"错误:clone()在Object中具有受保护的访问权限"
扩展A还应该clone()提供给B吗?如果是这样,那么i和j的值应该复制到l和m吗?这可能吗 ?
当Joshua Bloch提到在Java中破解了Cloneable接口时,为什么Prototype模式使用clone()方法来促进对象创建,而不是Java开发中的反模式?
"Cloneable被打破是一种耻辱,但它确实发生了." - 约书亚布洛赫
我正在编写一个类,在该类中我必须使用臭名昭著的“super.clone() 策略”覆盖clone() 方法(这不是我的选择)。
我的代码如下所示:
@Override
public myInterface clone()
{
myClass x;
try
{
x = (myClass) super.clone();
x.row = this.row;
x.col = this.col;
x.color = this.color;
//color is a final variable, here's the error
}
catch(Exception e)
{
//not doing anything but there has to be the catch block
//because of Cloneable issues
}
return x;
}
Run Code Online (Sandbox Code Playgroud)
一切都会好起来的,除了我不能color在不使用构造函数的情况下初始化,因为它是一个最终变量......有没有办法既使用 super.clone() 又复制最终变量?
java.lang.Cloneable接口的Java规范将自己定义为表示扩展它的任何对象也实现了clone()休眠的方法java.lang.Object.具体来说,它说:
类实现
Cloneable接口以向该java.lang.Object#clone()方法指示该方法合法地为该类的实例制作字段的字段副本.
对我来说,这意味着应该假设每个扩展的类Cloneable也都有一个public Object clone()方法.这使得很容易假设以下是有效的方法:
public static makeACloneFrom(Cloneable c)
{
return c.clone();
}
Run Code Online (Sandbox Code Playgroud)
然而,情况并非如此,因为整个Cloneable源代码(sans javadoc)很简单
package java.lang;
public interface Cloneable {
}
Run Code Online (Sandbox Code Playgroud)
这意味着它Cloneable#clone()不存在(并且尝试编译上面的示例方法会引发编译时错误,例如" cannot find symbol: method clone()").不应该Cloneable包含某些东西的源代码的效果public Cloneable clone();?
为什么我们不允许假设一个实现的类Cloneable有一个public Cloneable clone()方法?
我需要我的装备多态克隆(深层副本)类,即我需要的是这样的工作:
SuperType original = new SubType();
SuperType copy = original.clone();
Run Code Online (Sandbox Code Playgroud)
其中original.clone()可以用任何机制代替创建深层副本,而实际类型copy应该是SubType,因为original它也是一个SubType.
是clone()方法和Cloneable接口,实现这一目标的唯一途径?工厂方法和拷贝不能被用来构造函数,因为实际的类仅在运行时已知的,对不对?除了那些序列化 - 反序列化方法之外还有其他任何建议的方法,而Java深度克隆库是恕我直言的黑魔法甚至比clone()方法更糟糕吗?
谢谢,彼得
我正在尝试使用CRTP实现Clonable类.但是,我需要具有纯虚拟克隆方法的抽象类,由子类重写.为了实现这一点,我需要克隆函数来返回协变返回类型.我在下面制作了这段代码,编译器向我大喊这个错误:
main.cpp:12:5: error: return type of virtual function 'clone' is not covariant with the return type of the function it overrides ('B *' is not derived from 'AbstractClonable *')
Run Code Online (Sandbox Code Playgroud)
类'B'似乎是AbstractClonable的子类,甚至是双向的!我怎么解决这个问题?非常感谢你.我尝试使用clang 3.6和GCC 4.9.2
struct AbstractClonable {
virtual AbstractClonable* clone() const = 0;
};
template<typename T>
struct Clonable : virtual AbstractClonable {
T* clone() const override {
return new T{*dynamic_cast<const T*>(this)};
}
};
struct A : virtual AbstractClonable {
};
struct B : A, Clonable<B> {
};
Run Code Online (Sandbox Code Playgroud) cloneable ×10
java ×9
clone ×7
deep-copy ×3
c++ ×1
covariant ×1
crtp ×1
optimization ×1
performance ×1
serializable ×1