假设我们正在尝试在java中构建一个文档扫描程序类,它接受一个输入参数,即日志路径(例如C:\ document \ text1.txt)。根据性能/内存/模块性,您更喜欢以下哪种实现?
ArrayList<String> fileListArray = new ArrayList<String>();
fileListArray.add("C:\\document\\text1.txt");
fileListArray.add("C:\\document\\text2.txt");
.
.
.
//Implementation A
for(int i =0, j = fileListArray.size(); i < j; i++){
MyDocumentScanner ds = new MyDocumentScanner(fileListArray.get(i));
ds.scanDocument();
ds.resultOutput();
}
//Implementation B
MyDocumentScanner ds = new MyDocumentScanner();
for(int i=0, j=fileListArray.size(); i < j; i++){
ds.setDocPath(fileListArray.get(i));
ds.scanDocument();
ds.resultOutput();
}
我个人更喜欢A,因为它的封装,但由于创建了多个实例,它似乎更多的内存使用。我很好奇是否有答案,或者是另一个“这取决于情况/情况”的困境?
答案 0 :(得分:3)
虽然这显然是基于意见的,但我会尝试回答我的意见。
你接近A更好。您的文档扫描仪显然处理文件。这应该在构造时设置并保存在实例字段中。所以每种方法都可以参考这个领域。而且,构造函数可以对文件引用进行一些检查(null check,exists,...)。
您的方法B有两个非常严重的缺点:
构建文档扫描程序后,客户端可以轻松调用所有方法。如果之前没有设置文件,则必须处理&#34;非法状态&#34;可能是IllegalStateException
。因此,这种方法增加了该类的代码和复杂性。
客户端应该或可以执行一系列方法调用。在这样一个系列的中间再次使用完全其他文件再次调用文件设置方法很容易,打破了整个扫描工具。为避免这种情况,您的setter(对于文件)应该记住文件是否已经设置。这几乎自动导致接近A。
关于对象的创建:现代JVM在创建对象方面非常快。通常,没有可衡量的性能开销。处理时间(此处:扫描)通常要高得多。
答案 1 :(得分:2)
如果您不需要多个DocumentScanner
实例共存,我认为在循环的每次迭代中创建新实例都没有意义。它只是为垃圾收集器创建了工作,垃圾收集器必须释放每个实例。
如果数组的长度很小,那么你所选择的实现并没有多大区别,但是对于大型数组,实现B在内存方面效率更高(创建的实例少于GC没有& #39; t释放了)和CPU(GC的工作量减少了。)
答案 2 :(得分:1)
您是在实施DocumentScanner
还是使用现有的课程?
如果是后者,并且它被设计为能够连续解析多个文档,则可以像在变体B中一样重用该对象。
但是,如果您正在设计DocumentScanner
,我建议您将其设计为处理单个文档,甚至不使用setDocPath
方法。这导致该类中的可变状态较少,因此使其设计更容易。同样使用该类的实例也不易出错。
至于性能,除非实例化DocumentScanner
做了很多工作(比如实例化许多其他对象),否则不会有可测量的差异。如果由于世代垃圾收集器仅在短时间内使用Java,则实例化和释放Java中的对象非常便宜。