Java';原型&x27;模式-新建vs克隆vs class.newInstance
在我的项目中,有一些“原型”工厂通过克隆最终的私有实例来创建实例 这些工厂的作者表示,这种模式比调用“新”操作符提供更好的性能 通过谷歌找到一些线索,我没有发现任何相关的东西。 下面是一篇文章的小摘录 遗憾的是,clone()比 呼叫新的。然而,这是很多 比打电话快 java.lang.Class.newInstance(),以及 比我们自己的滚动要快一些 “克隆”法 对我来说,这看起来像是Java1.1时代的一个古老的最佳实践。Java';原型&x27;模式-新建vs克隆vs class.newInstance,java,performance,prototype-pattern,Java,Performance,Prototype Pattern,在我的项目中,有一些“原型”工厂通过克隆最终的私有实例来创建实例 这些工厂的作者表示,这种模式比调用“新”操作符提供更好的性能 通过谷歌找到一些线索,我没有发现任何相关的东西。 下面是一篇文章的小摘录 遗憾的是,clone()比 呼叫新的。然而,这是很多 比打电话快 java.lang.Class.newInstance(),以及 比我们自己的滚动要快一些 “克隆”法 对我来说,这看起来像是Java1.1时代的一个古老的最佳实践。 有人知道得更多吗?使用“现代”jvm时,这是一种好的做法吗?当然
有人知道得更多吗?使用“现代”jvm时,这是一种好的做法吗?当然,这种做法已经完全过时了。从那时起,Java虚拟机得到了极大的改进。创建对象非常便宜。另一个相关的实践,对象池,也已经过时,因为对象创建和清理的成本现在要高效得多。在某些情况下,它可能很有用(),但决不能成为这样的基本框架库的一部分 我建议找一些新的图书馆和/或一个新的项目来做;-) 查看这篇课堂文章,了解更多细节。否
哦,我需要更多的字符来回答。因此,让我进一步说明,除非有问题,否则这种微观优化是不合适的。如果有问题,那么你应该能够衡量它是否能让事情变得更好。Gee。这是我听过的最糟糕的想法之一 不要做奇怪的事。即使你已经测量并看到了一些明显的改善(在这种情况下,这种可能性为零),在做之前也要考虑很久。。谁知道它将在下一个JVM中修复。然后,您会看到一些奇怪的代码,它们的性能更差,难以阅读,并因此产生一些bug 我的意思是,开发JVM的人并不是白痴!使用
新建
我认为你应该去掉那段奇怪的代码。正如其他人所说,这是一种过时的做法。这是一种过时的模式,不幸的是,对于较新的JVM,它会在不提高性能的情况下给代码增加更多的膨胀
我希望我还有代码可以共享,但是不久前我对这个模式和使用“new”操作符做了一个简单的性能测试,我发现使用“new”操作符最坏的情况下至少和这个模式一样快,最好更快更有效。可能有一些我的测试没有涵盖的边缘情况,这仍然是一种有效的方法,但通常我会说避免这种模式
另一个注意事项是,如果它存在于现有的代码库中,我建议您不要太担心这个问题。但我也不会编写新的代码来扩展项目的更多部分的这种模式,除非不这样做会损害代码库的清晰性和一致性——在这一点上,您应该评估从长远来看从项目中重构这种代码是否明智。我所说的“智能”是指,在你的项目中重构这些代码会不会在将来节省开发和调试的时间>重构这些代码所需的时间量。我已经为classPerson
创建了简单的基准测试。我正在使用最新的OpenJDK 8:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
并得到以下结果:
Benchmark Mode Cnt Score Error Units
MyBenchmark.viaClone avgt 10 10.041 ± 0.059 ns/op
MyBenchmark.viaNew avgt 10 7.617 ± 0.113 ns/op
这个简单的基准测试表明,实例化新对象并从源对象设置相应属性所需的时间比克隆它少25%。我的DecimalFormat测试(OpenJDK 8/Windows/JMH 1.19)显示了完全相反的图像:
Benchmark Mode Cnt Score Error Units
Format.everyTimeCreate avgt 10 9326.967 ± 199.511 us/op
Format.useClone avgt 10 5102.397 ± 72.993 us/op
Format.useGlobalWithTL avgt 10 4605.604 ± 59.000 us/op
看来要回答什么性能更好并不是那么简单。谢谢你的链接,我知道这个设计有问题,但我需要一些“学术”证据!我只需要缓和一下回答:这对android开发者来说是无效的:google最佳实践促进了克隆/池的使用,而不是对象的创建,android是用Java编写的,但不是真正的Java,所以这在技术上是正确的。更准确地说,Sun的HotSpot JVM(以及其他类似的JVM)不再需要对象池。Dalvik是它自己的动物,在资源有限的设备上创建对象和GC可能既昂贵又痛苦,因此始终遵循目标平台/JVM的最佳实践。(不过,我希望情况不是这样,现在是这样。)