如何在Java中使用字段或局部变量初始化对象?
以下情况下的性能/可靠性情况如何:如何在Java中使用字段或局部变量初始化对象?,java,performance,initialization,Java,Performance,Initialization,以下情况下的性能/可靠性情况如何: public class A { private SomeObject a = new SomeObject(); //... public void method() { a.callSomeMethod(); } //... } 与: public class A { //... public void method() { SomeObject a = ne
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();
}
//...
}
我明白了,从可测试性的角度来看,第二个选择不是那么好。
但是性能和可靠性呢?你应该走哪条路?将对象初始化为文件并大量使用它,还是每次需要时都初始化它
后期编辑:对象的构造不会花费很长时间。这种方法被大量使用
以下情况下的性能/可靠性情况如何
它们完全不同,在第一种情况下,a
是类成员,在第二种情况下,a
仅在方法
的范围内已知。我不确定“比较”这两个代码的性能有多好
但是值得注意的是,第一个代码
someObject
中的。我不知道您调用了多少次方法
,您的问题在当前版本中很难回答。性能问题不是这里最大的问题
仅就性能而言,这取决于您的使用
第一个版本可能更好,因为您不必为每个方法调用创建新的SomeObject
如果您创建了大量a
s,并且只调用method
几次,那么第二种方法会更好。(如@Marko Topolnik建议的)
然而,这里最大的问题是正确性。在方法
的每次调用中使用相同的对象与在每次调用中使用新的SomeObject
不同
这个问题比性能更重要。主要区别在于变量的范围。首先是一个实例变量,然后是一个局部变量
如果对象只在该方法中使用,并且每次调用时都会更改,那么您可以使用第二种方法。实际上,如果您的
SomeObject
构造函数体包含执行可能需要很长时间的代码,那么在第二种情况下可能会出现一些真正的性能问题,因为在第二种情况下,每次调用A.method()
时,您都在构造SomeObject
对象。这取决于具体情况。
演出
如果您想要评估两个抽象选项之间的性能差异,就像您在这里看到的那样;最好的办法是夸大一切的规模。例如,假设SomeObject
实例化花费了过多的时间(比如600秒),并且您计划大量调用method()
(因为在项目扩展之前,性能问题通常不会实现)
很明显,选项1在多次调用method()
时会“执行”得更好,因为每次调用方法时,选项2都会导致一个巨大的操作。(是的,作为一个粗略的性能测试,您可以通过for循环运行每个选项并比较经过的时间,但应该很容易看出:在所有其他条件相同的情况下,创建一个对象n次要比创建一次对象花费更多的时间)
但在夸张的例子中,性能本身并不一定是在所有情况下支持选项1的理由。
建筑学
选择2
它实际上可以归结为SomeObject
的体系结构。什么是某个对象?可能是SomeObject
是一个在A
的生命周期内无法打开的对象;例如,它可能是某种流读取器,在资源从流中读取时锁定资源。在这种情况下,您可能不想让SomeObject
一直“打开”该资源;它应该在method()
调用的末尾处理
选择1
好吧,但也许SomeObject
类似于公开业务逻辑的服务或外观。正如您在问题中提到的,它“更适合于测试”,完整的答案是,是的,它为依赖注入提供了一个更容易的钩子,这是单元测试的关键组件。(虽然,通常它会被重写为private SomeObject a;
,使用类似于public a(SomeObject a){this.a=a;}
的构造函数,以遵循依赖注入/控制反转范例。但是,就本问题而言,最终结果是相同的。)
对于(设计良好的)服务或实用程序函数,您希望它能够自行(私下)处理对象处理。在这种情况下,使用率更高的模式是选项1,因为它为您提供了一个管理依赖关系的位置,而不是在使用它的每个方法中
你的选择
了解上述情况就足以做出明智的决定
- 方案1-服务、立面、公用设施等
- 方案2——需要处理的物体;实现
的对象,如Closable
、StreamReader
等FileWriter
是的。演出将会很受欢迎。在第一个场景中,并非每次输入method()时都会创建某个对象的对象。在第二种情况下,每次输入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循环和ca
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();
....
}