【问题标题】:Using variables to store values or directly get values from the objects?使用变量来存储值还是直接从对象中获取值?
【发布时间】:2012-10-05 13:26:39
【问题描述】:

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

将名称存储在变量中:

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());
}

我明白,在第一个场景中,我将创建一个新字符串,为其分配一个值,然后检索该值两次。这样我使用了更多的内存资源,对吗?

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

哪种方法更好?

【问题讨论】:

  • 在第一种方法中,您不是创建一个新字符串。所以这两种方法应该以相同的内存消耗结束。
  • 可能值得用反编译器检查生成的字节码,看看你的问题是否真的是一个问题; javac 可能会识别此用例并以一种或另一种方式对其进行优化,无论您以哪种方式使用 Java 编写它。

标签: java variables memory resources


【解决方案1】:

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

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

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

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

【讨论】:

  • 所以在第一种情况下,String name 和 bar.getName() 都指向内存中的同一个 String。如果我更改 bar.name 我并没有真正更改它,而是将其指向其他字符串,而字符串名称仍将指向旧值?
  • 没错。这就是为什么 java.lang.String 中的所有方法都返回一个新的 String 而不是修改它们被调用的对象的原因。
【解决方案2】:

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

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 的方法......太棒了!
  • @user1581900 你应该读他的书,我很喜欢 :) 另见 Robert C Martin 的“清洁代码”书 :)
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2014-02-22
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 2016-04-29
    • 1970-01-01
    相关资源
    最近更新 更多