以下情况的性能/可靠性图如何:
public class A {
private SomeObject a = new SomeObject();
//...
public void method() {
a.callSomeMethod();
}
//...
}
与
public class A {
//...
public void method() {
SomeObject a = new SomeObject();
a.callSomeMethod();
}
//...
}
我明白了,从可测试性的角度来看,第二种选择并不是那么好。 但是性能,可靠性如何 - 你应该走哪条路?要将对象初始化为一个文件并大量使用它或在每次需要时启动它?
稍后编辑:对象的构造不需要很长时间。该方法被大量使用。
答案 0 :(得分:2)
性能问题不是这里最大的问题。
仅谈性能,取决于您的使用情况。
第一个版本可以更好,因为您不会在每个方法调用中创建新的SomeObject
。
如果您创建了大量A
s并且只调用method
几次,则第二个更好。 (正如@Marko Topolnik建议的那样)
但是,这里最大的问题是正确性。在method
的每次通话中使用相同的对象与每次通话时使用新的SomeObject
不同。
这个问题比表现更重要。
答案 1 :(得分:1)
以下情况的性能/可靠性图片如何
它们完全不同,在第一种情况下a
是一个类成员,在第二种a
中仅在method
的范围内知道。我不确定“比较”这两个代码的性能有多好。
但值得注意的是,someObject
的每次调用都不会创建第一个代码method
。我不知道你打电话method
多少次,你的问题在目前的修订中难以回答。
答案 2 :(得分:1)
实际上,如果你的SomeObject
构造函数体包含执行可能需要很长时间的代码,那么在第二种情况下可能存在一些真正的性能问题,因为在第二种情况下,每次SomeObject
构造A.method()
对象时正在调用{1}}。
答案 3 :(得分:1)
如果您想评估两个抽象选项之间的性能差异,就像您在这里一样;最好的方法是夸大一切的规模。例如,假设SomeObject
需要花费过多的时间来实例化(例如,600秒),并且您计划大量调用method()
(因为在项目之前通常无法实现性能问题尺度)。
很明显:选项1将在多个method()
调用中“执行”更好,因为选项2每次调用方法时都会导致巨大的操作。 (是的,作为粗略的性能测试,您可以通过for循环运行每个选项并比较经过的时间,但应该很容易看到:所有其他都相同,创建一个对象n次将需要更多时间比创建一个对象一样。)
但在夸张的例子中表现本身并不一定是在所有情况下都支持选项1的理由。
它真正归结为SomeObject
的架构。 SomeObject
的内容是什么?可能SomeObject
是一个在A
的生命周期内无法保持打开的对象;例如,它可能是某种流式读取器,它在从流中读取资源时锁定资源。在这种情况下,您可能不希望SomeObject
一直“打开”阻止该资源;它应该在method()
电话结束时处理。
好吧,但也许SomeObject
就像服务或Facade那样暴露了业务逻辑。正如你在问题中提到的那样,它“更适合测试”,而完全答案是,是的,它为依赖注入提供了一个更容易的钩子,这是单元测试的关键组件。 (虽然,通常它将被重写为private SomeObject a;
,使用类似public a (SomeObject a) { this.a = a; }
的构造函数来遵循控制范例的依赖注入/反转。但是,最终结果是相同的这个问题。)
对于(精心设计的)服务或实用程序功能,您希望它本身(私下)处理对象处理。在这种情况下,使用得更多的模式是选项1,因为它为您提供了一个管理依赖项的位置,而不是在使用它的每个方法中。
了解上述内容应足以做出明智的决定。
Closable
的对象,如StreamReader
,FileWriter
等答案 4 :(得分:1)
是。表现会受到打击。在第一个场景中,每次输入method()时都不会创建SomeObject的对象。在第二种情况下,每次输入method()时,都会创建一个新的SomeObject,这通常不是优选的。但另一方面,还必须查看对象和垃圾收集机制的范围。在第二种情况下,只要方法调用返回/结束,创建的对象的范围也会丢失。因此,它将可用于垃圾收集器。所以,如果内存是一个问题,那么你可能想要第二个选项。即,如果要创建几百个对象,那么您可能需要考虑第二个选项。选项1的缺点是只要父对象 - 类A的实例存在,所有组合对象都将持久存在。如果你继续这样做
public class A {
private SomeObject a1 = new SomeObject();
private SomeObject a2 = new SomeObject();
private SomeObject a1000 = new SomeObject();
//...
public void method() {
a.callSomeMethod();
}
//...
}
上面的代码效率低于使用for循环和调用method()1000次并且每次调用method()时都创建一个对象。
但话又说回来,这是一个设计问题。根据您的需求,一种选择比另一种更好。 如果我错了,请纠正我。
答案 5 :(得分:1)
其他答案已经涵盖了这一点,所以我不会重复太多。这实际上取决于A
和SomeObject
的用途和结构。根据具体情况,还有其他选择。如果对象创建是SomeObject
的问题,并且对method
的调用次数相对较少,则使用延迟初始化可能有意义:
public class A{
private SomeObject o;
public void method(){
if(o == null){
o = new SomeObject();
}
o.callSomeMethod();
}
}
此外,将引用标记为最终可能有助于提高性能(至少用于):
public class A{
private final SomeObject = new SomeObject();
....
}
答案 6 :(得分:0)
主要区别在于变量的范围。第一个是实例变量,后来是局部变量。
如果Object将仅在该方法中使用并且将在每次调用时更改,那么您可以采用第二种方法