如何克隆ArrayList并在Java中克隆其项目?
例如,我有:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
Run Code Online (Sandbox Code Playgroud)
我希望那些物品clonedList与狗列表中的物品不同.
做(之后mkdir repo和cd repo)有什么区别:
git init
git remote add origin git://github.com/cmcculloh/repo.git
git fetch --all
git pull origin master
Run Code Online (Sandbox Code Playgroud)
和
git clone git://github.com/cmcculloh/repo.git
Run Code Online (Sandbox Code Playgroud)
我的意思是,显然一个更短,但除此之外他们基本上做同样的事情?
在Ruby的文档的dup说:
在一般情况下,
clone并dup可能在派生类不同的语义.虽然clone用于复制对象(包括其内部状态),但dup通常使用后代对象的类来创建新实例.
但是当我做一些测试时,我发现它们实际上是相同的:
class Test
attr_accessor :x
end
x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7
Run Code Online (Sandbox Code Playgroud)
那么这两种方法有什么区别?
我有一个通用词典词典,我想基本上做一个克隆()的任何建议.
我希望在Google上找到这四者之间的差异,我希望有关于此的大量信息,但四个电话之间确实没有任何可靠的比较.
我开始尝试编译一种基本的一目了然的看看这些系统调用之间的差异,这就是我得到的.所有这些信息是否正确/我错过了什么重要的事情?
Fork :fork调用基本上复制了当前进程,几乎在所有方面都是相同的(并非所有内容都被复制,例如,某些实现中的资源限制,但想法是尽可能创建尽可能接近的副本).
新进程(子进程)获取不同的进程ID(PID),并将旧进程(父进程)的PID作为其父PID(PPID).因为这两个进程现在运行的代码完全相同,所以它们可以通过fork的返回代码告诉哪个进程 - 子进程为0,父进程获取子进程的PID.当然,这就是假设fork调用有效 - 如果没有,则不创建子节点并且父节点获取错误代码.
Vfork:vfork和fork之间的基本区别在于,当使用vfork()创建新进程时,父进程将暂时挂起,子进程可能会借用父进程的地址空间.这种奇怪的状态一直持续到子进程退出或调用execve(),此时父进程继续.
这意味着vfork()的子进程必须小心,以避免意外修改父进程的变量.特别是,子进程不能从包含vfork()调用的函数返回,并且它不能调用exit()(如果需要退出,它应该使用_exit();实际上,对于子进程也是如此正常的fork()).
Exec :exec调用是一种基本上用新程序替换整个当前进程的方法.它将程序加载到当前进程空间并从入口点运行它.exec()用函数指向的可执行文件替换当前进程.除非存在exec()错误,否则控件永远不会返回到原始程序.
Clone :克隆,作为fork,创建一个新进程.与fork不同,这些调用允许子进程与调用进程共享其执行上下文的一部分,例如内存空间,文件描述符表和信号处理程序表.
使用clone创建子进程时,它将执行函数应用程序fn(arg).(这与fork不同,fork从原始fork调用开始继续执行.)fn参数是指向子进程在执行开始时调用的函数的指针.arg参数传递给fn函数.
当fn(arg)函数应用程序返回时,子进程终止.fn返回的整数是子进程的退出代码.子进程也可以通过调用exit(2)或在收到致命信号后明确终止.
获得的信息形式:
感谢您抽时间阅读 !:)
我想知道是否有推荐的方法在java中进行深度克隆/复制实例.
我有三个解决方案,但我可以错过一些,我想得到你的意见
编辑:包括Bohzo的提议和改进问题:它更多的是深度克隆而不是浅层克隆.
在属性之后通过hand属性编写克隆代码并检查是否也克隆了可变实例.
亲:
- 控制将要执行的操作
- 快速执行
缺点:
- 编写和维护繁琐
- 容易出错(复制/粘贴失败,缺少属性,重新分配的可变属性)
使用您自己的反射工具或外部帮助程序(如jakarta common-beans),可以轻松编写一个通用的复制方法,该方法可以在一行中完成工作.
亲:
- 易于编写
- 没有维护
缺点:
- 对发生的事情的控制较少
- 如果反射工具也没有克隆子对象,则容易出现可变对象的错误
- 执行速度较慢
使用为您执行此操作的框架,例如:
commons-lang SerializationUtils
Java Deep Cloning Library
Dozer
Kryo
亲:
- 与反思一样
- 更多地控制将要克隆的内容.
缺点:
- 即使在层次结束时,每个可变实例都被完全克隆
- 执行起来可能非常慢
javassit,BCEL或cglib可能用于生成专用克隆器,只需单手写入.为此目的,有人知道使用这些工具之一的lib吗?
我错过了什么?
你会推荐哪一个?
谢谢.
我有一个InputStream,我传递给一个方法来做一些处理.我将在其他方法中使用相同的InputStream,但在第一次处理之后,InputStream似乎在方法内部关闭.
我如何克隆InputStream发送到关闭他的方法?有另一种解决方案吗?
编辑:关闭InputStream的方法是来自lib的外部方法.我无法控制关闭与否.
private String getContent(HttpURLConnection con) {
InputStream content = null;
String charset = "";
try {
content = con.getInputStream();
CloseShieldInputStream csContent = new CloseShieldInputStream(content);
charset = getCharset(csContent);
return IOUtils.toString(content,charset);
} catch (Exception e) {
System.out.println("Error downloading page: " + e);
return null;
}
}
private String getCharset(InputStream content) {
try {
Source parser = new Source(content);
return parser.getEncoding();
} catch (Exception e) {
System.out.println("Error determining charset: " + e);
return "UTF-8";
}
}
Run Code Online (Sandbox Code Playgroud) 看来PHP对象是通过引用传递的.甚至赋值运算符似乎也没有创建Object的副本.
这是一个简单,人为的证明:
<?php
class A {
public $b;
}
function set_b($obj) { $obj->b = "after"; }
$a = new A();
$a->b = "before";
$c = $a; //i would especially expect this to create a copy.
set_b($a);
print $a->b; //i would expect this to show 'before'
print $c->b; //i would ESPECIALLY expect this to show 'before'
?>
Run Code Online (Sandbox Code Playgroud)
在两个印刷案例中,我都在"追求"
那么,我如何通过值传递$ a到set_b(),而不是通过引用?
我有一个ArrayList<String>我想要寄回的副本. ArrayList有一个克隆方法,具有以下签名:
public Object clone()
Run Code Online (Sandbox Code Playgroud)
调用此方法后,如何将返回的Object转换回ArrayList<String>?