StringBuffer是否与Ruby中的string相同,Symbols是否与常规Java字符串相同?



我刚开始读《雄辩的Ruby》这本书,我已经读到了关于Ruby中的符号的那一章。

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

那么,Ruby中符号的目的实际上与Java中的"正常"字符串对象相同吗?它是一个赋予程序员优化内存的功能吗?

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

符号在Ruby中与字符串很接近,但它们并不等同于普通的Java字符串,尽管它们也有一些共性,比如不变性。但是有一个细微的区别——有不止一种方法可以获得对Symbol的引用(稍后会详细介绍)。

在Ruby中,完全可以来回转换两者。String#to_sym用于将字符串转换为符号,Symbol#to_s用于将符号转换为字符串。那么区别是什么呢?

为Symbol引用RDoc:

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

符号是唯一标识符。如果Ruby解释器第一次被:mysymbol绊倒,会发生这样的事情:在内部,如果符号还不存在,它会被存储在一个表中(很像解析器使用的"符号表";这是使用C函数rb_intern(在CRuby/MRI中)来实现的,否则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中String的对象相等,你只有在比较String的完全相同的引用时才能实现,而在Ruby中,就像你在上面的例子中看到的那样,可以通过多种方式获得对Symbol的引用。

符号的唯一性使它们成为哈希中的完美键:与常规字符串相比,查找性能得到改善,因为您不必显式地哈希您的键,因为它将被字符串所要求,您可以简单地使用符号的唯一标识符直接查找。通过写:somesymbol,你告诉Ruby"给我一个你存储在标识符"某个符号"下的东西"。因此,当您需要唯一标识事物时,符号是您的首选,例如:

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

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

使用字符串当你需要…嗯…类似字符串的行为。

关于这个话题的一些文章:

    Ruby符号
  • 符号不是不可变字符串
  • 查看Ruby符号的13种方法

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

但是,如果在Java运行时动态地创建一个String,两个String完全可以指向不同的对象,并且仍然包含相同的文本。不过,你可以通过内部化String对象(调用String.intern())来强制实现这一点,参见Java API

最新更新