1

采取以下方法(用 Ruby 编写,但这个问题可以应用于大多数 OO 语言)

# Getter method which returns an alert
def alertView
  _alertView = AlertView.new
  _alertView.title = "This is the title"
  _alertView.body = "This is the body of my alert"
  _alertView
end

假设在应用程序的整个生命周期中定期调用此方法。标题和正文属性字符串每次都会被实例化为新对象。

为了优化这一点,我们可以执行以下操作:

ALERT_TITLE = "This is the title"
ALERT_BODY  = "This is the body of my alert"

# Getter method which returns an alert
def alertView
  _alertView = AlertView.new
  _alertView.title = ALERT_TITLE
  _alertView.body = ALERT_BODY
  _alertView
end

这样,ALERT_TITLEandALERT_BODY字符串只在定义类时实例化一次,然后在整个应用程序的生命周期中重用。

我的问题是:第二种方法是最优的吗?虽然这意味着垃圾收集器的工作量更少并且内存使用可能更稳定,但这也意味着应用程序一直在占用更多内存,而不是释放当前不需要的对象。我在将它应用到我的应用程序中的所有常量字符串或根本不应用这种方法以及在需要时定义每个字符串之间左右为难。

第三种方法是使用类变量,但与第二种方法相比,它提供的唯一优势是变量是延迟加载的。

# Getter method which returns an alert
def alertView
  _alertView = AlertView.new
  _alertView.title = @@alert_title ||= "This is the title"
  _alertView.body = @@alert_body ||= "This is the body of my alert"
  _alertView
end
4

2 回答 2

3

上述两种变体并不完全相等。观察:

1.9.3p194 :001 > A = 'a'
 => "a" 
1.9.3p194 :002 > s1 = A # constant assignment
 => "a" 
1.9.3p194 :003 > s2 = A
 => "a" 
1.9.3p194 :004 > s1 << 'b'
 => "ab" 
1.9.3p194 :005 > s2 # you changed s2 as well!
 => "ab" 
1.9.3p194 :006 > s1 = 'a' # literal assignment
 => "a" 
1.9.3p194 :007 > s2 = 'a'
 => "a" 
1.9.3p194 :008 > s1 << 'b'
 => "ab" 
1.9.3p194 :009 > s2 # s2 stayed the same.
 => "a" 

当两个变量被分配相同的常量时,内存中仍然只有一个字符串实例。当您分配文字字符串时,每个变量在内存中都有自己的实例(这不适用于符号,您在另一条评论中正确地指出了这一点)。因此,一切都取决于您想要实现(或避免)什么,创建多少实例等等。

如果问题真的与字符串有关,就像您的示例中那样,我会说您不再关心效率并开始关心代码可读性,因为所有这些都是当今程序可用内存的一小部分

所以,从程序员的角度来看,我建议你做任何你认为更清洁的事情。

于 2012-06-24T17:30:13.140 回答
0

好吧,无论如何,在 C# 和 Java 中,这些都同样是最优的。由于所谓的“字符串实习”,编译器会识别出您每次都在实例化相同的字符串,因此它将为每个新的 AlertView 对象提供与您正在使用的两个字符串相同的两个对象引用。

现在,Ruby 是一种解释性语言,而且……不是 C# 或 Java……我不确定它是否这样做。所以,希望其他人也能回答。但我的第一个猜测是它确实实现了字符串内部化——仅仅是因为,即使它被解释了,它仍然应该能够在遇到字符串常量时轻松识别它们,并以其他语言处理它们的相同(优化)方式处理它们。

于 2012-06-24T16:18:04.960 回答