只有当一个字段表示某个对象的状态时,才将值设置为有意义。
我想知道在某些情况下是否应避免使用这条“规则”。
这是一个例子,假设这个类:
public class DbCar {
private ResultSet rs;
public DbMapper(ResultSet rs) {
this.rs = rs;
}
public Car buildObject(){
//.....does some mappings, then returns the builded car ....
}
}
因此我们看到ResultSet存储为成员变量,因为每个DbMapper都像DbCar一样从JDBC查询中操作检索到的ResultSet,所以它是有意义的。
我们的呼叫者看起来如下:
while (rs.next()) {
items.add(new DbCar(rs)).buildObject();
}
但想象一下,当前查询返回了15000条记录。
简而言之=>创建了15000个DbCar对象实例。
所以我的问题是:垃圾收集器是否足够有效,以至于我不应该担心这么多实例?
当然,为了避免所有这些实例,我们可以按如下方式重构代码:
public class DbCar {
public Car buildObject(ResultSet rs) {
//.....does some mappings, then returns the builded car ....
}
}
在这种情况下,将创建一个DbCar实例(在当前线程和当前方法中),调用者如下所示:
DbCar dbCar = new DbCar();
while (rs.next()) {
items.add(dbCar.buildObject(rs));
}
那么,我应该选择哪种解决方案?信任垃圾收集器,使用更优雅的代码或编码,如使用本地参数方法更程序化的编码风格?
为了更难以做出选择,想象一下DbCar类将其“构建”方法划分为优雅的小方法,每个方法都专门用于特定的责任,例如:
“buildEngine”,“buildDoors”等...如果选择本地参数,我必须将ResultSet传递给所有这些方法...无聊和redondant不是吗?
答案 0 :(得分:4)
第二是更好。垃圾收集器没有15000个对象,但建议不要挂在结果集对象上。因为这个原因,#2更好
答案 1 :(得分:2)
我相信垃圾收集器可以做得很好,并选择最清晰的实现。如果您稍后发现这会导致性能问题,那么您可以进行重构。你应该总是做更干净的实现,除非你有充分的理由不这样做(比如一个分析器向你展示这是一个瓶颈而且你应该失去一些清晰度以使其更快)。
如果GC无法妥善处理,我会感到惊讶。
答案 2 :(得分:2)
这对GC不构成问题,但这一切都归结为您的应用要求。
在之前的项目中,我参与开发了一个非常大的“近实时”应用程序,该应用程序在Solaris服务器上运行(需要10GB的RAM才能启动)应用程序每隔4秒左右创建150000个DTO对象。 。乍一看这对GC没有任何影响,但是在一些工作时间之后,用户开始抱怨软件丢失了来自硬件的数据。我们花了很长时间来调查这个问题,我们终于发现GC正在使用完整的CPU来清理未使用的对象,这使得应用程序看起来像挂了一秒左右(相信我,数据丢失的第二个成本更高)超过1000美元)
答案 3 :(得分:0)
您的特殊问题主要是功能设计问题。在设计程序时,通常不应该担心垃圾收集器。如果你必须在GC中思考,我认为你正在开发使用非常少的内存的非功能性需求的应用程序,或者你正在优化一个非常大的架构。这是你的情况吗?
在那里你可以找到实现这样的模板的模式。我正在引用Spring JDBC Template,例如:
http://static.springsource.org/spring/docs/2.0.x/reference/jdbc.html