使用变量存储值或直接从对象获取值?

时间:2012-10-05 13:26:40

标签: java variables memory resources

场景是我需要至少访问两次值。即我正在使用记录器来跟踪应用程序中发生的情况。我想记录对象的名称,该函数正在处理,稍后使用相同的名称(即检查它是否包含某些字符串或将其放入数组中)。

将名称存储在变量中:

foo(Bar bar){
    String name = bar.getName();
    logger.info("I am working with "+name);
    this.doSomethingWith(name);
}

或者两次调用getName():

foo(Bar bar){
    logger.info("I am working with "+bar.getName());
    this.doSomethingWith(bar.getName());
}

据我所知,在第一个场景中,我将创建一个新的String,为其赋值,然后检索此值两次。这样我使用更多的内存资源,对吗?

在第二种情况下,我是否访问了对象栏两次,然后两次访问它的名称。我想这不是一种干燥方法。但另一方面,我不是在记忆中重复自己,对吗?

哪种方法更好?

3 个答案:

答案 0 :(得分:3)

在第一个示例中,您没有使用更多内存,因为String是一个不可变对象。因此,对String的任何引用都只是指向内存中同一对象的指针。

后一个选项还存在一些线程安全问题,其中getName()的结果可能会在调用之间发生变化。尽管可能不太可能,但您可能需要考虑这一点。

考虑到这一点,我会推荐第一个选项,即使它更“说话”。

注意:getName()也可能是通过计算生成的,在这种情况下,您实际上最终会使用比第一种方法更多的内存。

答案 1 :(得分:1)

您的Bar应该是不可变类(对于大多数情况而言)。对于不可变类,这些方法是相同的,因此您可以选择任何您喜欢的方法。

只有Bar可变时才会出现任何实际问题,因此bar.name的值可以在2次读取之间发生变化。但是这种情况会使用Bar作为域对象(它似乎是)毫无意义。您可以通过在bar顶部创建foo()的本地副本来解决此类问题。然后,再次,一旦你有原始bar的本地副本,你可以选择你喜欢的任何方式。

所以,这是品味问题。是的,在第一种情况下,可以浪费一点内存用于本地引用,但最有可能的是,JVM会优化它以使其在字节码级别上看起来像第二种方式。

答案 2 :(得分:1)

就个人而言,我更喜欢第二种方法。 实际上,我通常只在必要时创建临时变量。

Martin Fowler(http://en.wikipedia.org/wiki/Martin_Fowler)也遵循本指南。他在我读过的书中谈到了这一点:

http://www.amazon.fr/Refactoring-Improving-Design-Existing-Code/dp/0201485672

关于这个主题的书的免费摘录在这里:

http://sourcemaking.com/refactoring/replace-temp-with-query

有些人会认为删除临时变量可能会导致性能问题。

正如Martin Fowler所说:

  

在这种情况下,您可能会担心表现。和其他一样   性能问题,让它暂时滑动。九次出局   十,没关系。当它重要时,你将解决问题   在优化期间。有了更好的代码,你会经常   找到更强大的优化,没有你会错过   重构。如果情况变得更糟,那么放温度就很容易了   回来。

但无论如何,这是一个品味问题。有些人发现第一种方法更具可读性,第二种方式则更有可我真的更喜欢第二种,因为我讨厌临时变量添加没有实际值的行:)