【问题标题】:Is StringBuffer the same as Strings in Ruby and Symbols the same as regular Java strings?StringBuffer 是否与 Ruby 中的字符串相同,而 Symbols 是否与常规 Java 字符串相同?
【发布时间】:2011-10-07 16:27:45
【问题描述】:

我刚开始阅读这本书Eloquent Ruby,我已经读到了关于Ruby 中的符号的章节。

Ruby 中的字符串是可变的,这意味着每个字符串都会分配内存,因为内容可以更改,即使内容相同。如果我需要 Java 中的可变字符串,我会使用 StringBuffer。然而,由于常规 Java 字符串是不可变的,因此一个字符串对象可以被多个引用共享。因此,如果我有两个内容为“Hello World”的常规字符串,则两个引用都指向同一个对象。

那么,Ruby 中 Symbols 的用途实际上与 Java 中的“普通”String 对象相同吗?它是给程序员优化内存的功能吗?

我在这里写的东西是真的吗?还是我误解了符号的概念?

【问题讨论】:

  • 不同(或相等)的字符串可以共享相同的char[],但不是必须的。此外,String 变量可以指向 Java 中相同或不同的对象。最后一点对可变对象和不可变对象一样有效。

标签: java ruby string symbols


【解决方案1】:

不同之处在于,如果 Java 字符串包含相同的文本,则它们不需要指向相同的对象。在代码中声明常量字符串时,通常是这种情况,因为编译器会将其放入常量池中。

但是,如果您在 Java 中动态创建一个字符串,两个字符串可以完美地指向不同的对象,并且仍然包含相同的文字文本。但是,您可以通过内部化 String 对象来强制执行此操作(调用 String.intern(),请参阅 Java API

一个很好的例子可以在here找到。

【讨论】:

    【解决方案2】:

    Symbol 与 Ruby 中的字符串很接近,但它们并不等同于常规的 Java 字符串,尽管它们也有一些共同点,例如不变性。但是有一点点不同 - 获得对符号的引用的方法不止一种(稍后会详细介绍)。

    在 Ruby 中,完全可以将两者来回转换。有 String#to_sym 可以将 String 转换为 Symbol,还有 Symbol#to_s 可以将 Symbol 转换为 String。那么区别是什么呢?

    引用符号的 RDoc:

    在程序执行期间,将为给定名称或字符串创建相同的 Symbol 对象,而不管该名称的上下文或含义。

    符号是唯一的标识符。如果 Ruby 解释器第一次遇到问题,假设 :mysymbol,会发生以下情况:在内部,如果符号不存在,则将其存储在表中(很像解析器使用的“符号表”;这个使用 CRuby/MRI 中的 C 函数 rb_intern 发生),否则 Ruby 将在表中查找现有值并使用它。在创建符号并将其存储在表中之后,从那时起,无论您在何处引用符号 :mysymbol,您都将获得相同的对象,即存储在该表中的对象。

    考虑这段代码:

    sym1 = :mysymbol
    sym2 = "mysymbol".to_sym
    
    puts sym1.equal?(sym2) # => true, one and the same object
    
    str1 = "Test"
    str2 = "Test"
    
    puts str1.equal?(str2) # => false, not the same object
    

    注意区别。它说明了 Java 字符串和 Ruby 符号之间的主要区别。如果您希望 Java 中字符串的对象相等,则只有比较该字符串的完全相同的引用才能实现它,而在 Ruby 中,可以通过多种方式获取对符号的引用,如上例所示。

    符号的唯一性使它们成为哈希中的完美键:与常规字符串相比,查找性能得到了提高,因为您不必像字符串那样显式地对键进行哈希处理,您可以简单地使用符号的唯一直接查找的标识符。通过写:somesymbol,你告诉Ruby“把你存储在标识符'somesymbol'下的东西给我”。因此,当您需要唯一标识事物时,符号是您的首选:

    • 哈希键
    • 命名或引用变量、方法和常量名称(例如 obj.send :method_name )

    但是,正如 Jim Weirich 在下面的文章中指出的那样,符号不是字符串,即使在鸭子类型的意义上也不是。您不能连接它们或检索它们的大小或从中获取子字符串(除非您先将它们转换为字符串)。所以何时使用字符串的问题很简单——正如 Jim 所说:

    在需要时使用字符串……嗯……类似字符串的行为。

    关于该主题的一些文章:

    【讨论】:

    • 谢谢,感谢您的努力,但是我很难理解 Symbol 对象是什么,何时使用它,以及为什么 if 与 String 不同。我很抱歉。我还是不明白。
    • @Jolly:我又添加了两篇文章,并试图指出何时使用哪个,希望对您有所帮助?
    • 在多次阅读您的帖子后,如果我说我理解它,我会撒谎,很不幸。我对解释器/编译器在内部所做的事情也不是很好。我越来越困惑,我什至不明白什么是符号。
    猜你喜欢
    • 2019-01-11
    • 2013-12-16
    • 2022-06-28
    • 2011-04-07
    • 2015-03-30
    • 2017-02-09
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多