Java';原型&x27;模式-新建vs克隆vs class.newInstance

Java';原型&x27;模式-新建vs克隆vs class.newInstance,java,performance,prototype-pattern,Java,Performance,Prototype Pattern,在我的项目中,有一些“原型”工厂通过克隆最终的私有实例来创建实例 这些工厂的作者表示,这种模式比调用“新”操作符提供更好的性能 通过谷歌找到一些线索,我没有发现任何相关的东西。 下面是一篇文章的小摘录 遗憾的是,clone()比 呼叫新的。然而,这是很多 比打电话快 java.lang.Class.newInstance(),以及 比我们自己的滚动要快一些 “克隆”法 对我来说,这看起来像是Java1.1时代的一个古老的最佳实践。 有人知道得更多吗?使用“现代”jvm时,这是一种好的做法吗?当然

在我的项目中,有一些“原型”工厂通过克隆最终的私有实例来创建实例

这些工厂的作者表示,这种模式比调用“新”操作符提供更好的性能

通过谷歌找到一些线索,我没有发现任何相关的东西。 下面是一篇文章的小摘录

遗憾的是,clone()比 呼叫新的。然而,这是很多 比打电话快 java.lang.Class.newInstance(),以及 比我们自己的滚动要快一些 “克隆”法

对我来说,这看起来像是Java1.1时代的一个古老的最佳实践。
有人知道得更多吗?使用“现代”jvm时,这是一种好的做法吗?

当然,这种做法已经完全过时了。从那时起,Java虚拟机得到了极大的改进。创建对象非常便宜。另一个相关的实践,对象池,也已经过时,因为对象创建和清理的成本现在要高效得多。在某些情况下,它可能很有用(),但决不能成为这样的基本框架库的一部分

我建议找一些新的图书馆和/或一个新的项目来做;-)

查看这篇课堂文章,了解更多细节。


哦,我需要更多的字符来回答。因此,让我进一步说明,除非有问题,否则这种微观优化是不合适的。如果有问题,那么你应该能够衡量它是否能让事情变得更好。

Gee。这是我听过的最糟糕的想法之一

不要做奇怪的事。即使你已经测量并看到了一些明显的改善(在这种情况下,这种可能性为零),在做之前也要考虑很久。。谁知道它将在下一个JVM中修复。然后,您会看到一些奇怪的代码,它们的性能更差,难以阅读,并因此产生一些bug

我的意思是,开发JVM的人并不是白痴!使用
新建


我认为你应该去掉那段奇怪的代码。

正如其他人所说,这是一种过时的做法。这是一种过时的模式,不幸的是,对于较新的JVM,它会在不提高性能的情况下给代码增加更多的膨胀

我希望我还有代码可以共享,但是不久前我对这个模式和使用“new”操作符做了一个简单的性能测试,我发现使用“new”操作符最坏的情况下至少和这个模式一样快,最好更快更有效。可能有一些我的测试没有涵盖的边缘情况,这仍然是一种有效的方法,但通常我会说避免这种模式


另一个注意事项是,如果它存在于现有的代码库中,我建议您不要太担心这个问题。但我也不会编写新的代码来扩展项目的更多部分的这种模式,除非不这样做会损害代码库的清晰性和一致性——在这一点上,您应该评估从长远来看从项目中重构这种代码是否明智。我所说的“智能”是指,在你的项目中重构这些代码会不会在将来节省开发和调试的时间>重构这些代码所需的时间量。

我已经为class
Person
创建了简单的基准测试。我正在使用最新的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的最佳实践。(不过,我希望情况不是这样,现在是这样。)