为什么像Java这样的语言区分字符串和字符,而其他语言却没有呢?

2024-04-25 15:13:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我注意到像Java这样的语言有一个char原语和一个string类。其他语言如Python和Ruby只有一个string类。这些语言使用长度为1的字符串来表示字符。在

我想知道这种区别是否是因为历史原因。我知道直接影响Java的语言有char类型,但没有字符串。字符串是用char*或char[]形成的。在

但我不确定这样做是否有真正的目的。我也很好奇在某些情况下,一种方法是否比另一种方法更有优势。在

为什么像Java这样的语言区分char原语和string类,而Ruby和Python这样的语言却没有呢?

当然,它一定有某种设计上的顾虑,不管是惯例、效率、清晰度、实现的容易程度等等。可以说,语言设计者真的只是从帽子里挑了一个字符表示吗?在


Tags: 方法字符串目的语言类型string情况原因
3条回答

编辑1添加了许多到源代码的链接;改进了Lisp的历史故事;回答了Java为什么有灵长类动物。 edit2评论现代脚本语言,解释效率如何不再是一个问题

在过去,内存是昂贵的,即使是简单的计算机也只有几千字节。您必须同意的典型服务条款将超过整个系统的RAM。这意味着数据结构必须比现在设计的要小得多。在

计算机始于20世纪40年代的英国和美国,这些工程师所需的最小字符集是没有任何令人兴奋的口音的西欧字母表。0-9,A-Z和A-Z是62个字符。加上31个控制字符,空格和一些标点符号,你就可以把所有这些放入7位。完美的电传打字机。在

现在,这7位可以在不同的架构上进行不同的布局。如果您使用IBM,您必须知道EBCDIC与{a2}完全不同。在

60年代和70年代的语言反映了这些问题,并将字符串压缩到尽可能小的空间中:

  • Pascal:字节的压缩数组-固定长度且不以null结尾
  • C: 以空结尾的字节序列(通常被认为是一个数组,使用了一个疯狂的黑客思想,即数组下标就是pointer arithmetic
  • Fortran 66:字符串?你不需要他们。将字符存储在整数中,并使用读、写和格式

作为这些语言的程序员,我可以说这很糟糕。尤其是大多数商业程序需要大量的文本输入和操作。随着内存变得越来越便宜,程序员倾向于先编写字符串实用程序,然后才能做任何有效率的事情。在

固定长度的字符串(如Pascal)是有效的,但是如果您需要扩展或收缩它们(即使是一个字符),则会很尴尬。在

C的以null结尾的方法有一个缺点,即长度没有与字符串一起存储,因此很容易覆盖缓冲区并使应用程序崩溃。这些错误仍然是计算机不安全的主要原因。有两种解决方法:

  • 每次写入时检查字符串长度:这意味着扫描内存,直到找到空字符为止。丑陋的
  • malloc新建内存并将字符串复制到新内存中,然后free

在80年代,越来越多的标准库被引入来处理字符串,这些字符串是由工具供应商和操作系统供应商提供的。标准化方面有一些重大举措,但各方为了控制标准而针锋相对,这很难看。在

日益国际化也带来了另一个问题——国际字符集。首先,ASCII被扩展到8位,作为不同欧洲语言(口音、希腊语、西里尔文)的ISO 8859-1,然后Unicode将计算机完全带到了世界的各个角落。这就带来了字符编码的问题,比如UTF-8UTF-16以及如何在这些不同的方法之间进行转换。在

我还应该注意到,Lisp引入了垃圾回收。这解决了malloc/free的复杂性。Lisp强大的数组和序列库可以自然地处理字符串。在

第一个将这些趋势结合在一起的主要流行语言是Java。它结合了语言的三个改进:

  1. 国际化和Unicode:不同的数据类型Character和原语{}
  2. 封装:固定长度与空终止的问题可以通过以下方式解决:
    1. 不变的
    2. VM和GC中的巧妙优化
  3. 库:所有基本的字符串操作特性都在语言中进行了标准化。在

现在有些语言中每个值都是一个对象。但是当Java被构想出来的时候在90年代末,GC和JIT/Hotspot技术远没有现在快(至少部分是由于RAM的限制,但是算法也得到了改进)。Gosling was concerned about performance并保留原始数据类型。在

另一点:在Java中,有一个字符类是很自然的——它是许多操作和实用方法的自然归宿,比如isWhiteSpace()和{},后者在日语、韩语和印度语中有点复杂。在

Python使用poor early decision将字符定义为8位ASCII;首先引入另一种数据类型(unicode),可以看到由此产生的问题,这种数据类型与Python 3.x的复杂迁移是完全不同和不兼容的

现代语言(包括脚本语言)遵循关于字符串库应该如何显示的广泛共识,例如Java和Python。在

每种语言都是为特定的目的而设计的,因此以不同的方式平衡相互竞争的设计关注点。在过去的60年里,现代语言在性能和内存方面都有了巨大的改进,因此它们比CPU和RAM的效率更有利于泛化、纯度和实用性。对于脚本语言来说,这一点是明确的,因为脚本的性质已经做出了这样的决定。因此,现代语言往往只有高级字符串类型。在

TL/DR早期的计算机内存有限,迫使最简单的实现。现代语言得益于GCs识别国际化(8bit->;16bit)字符并封装字符串数据类型,从而使字符串操作安全而简单。在

现在,我对这件事的看法可能会以一种或另一种形式反映这里的一些答案,但无论如何,我还是要说:

是的,(就像其他人提到的那样)像C这样的低级语言比Perl、Ruby或Python这样的脚本语言更考虑优化、性能和机器级的细节。这种“完全控制”心态的后果是,与脚本语言相比,您通常有更多的事情要担心。在

我想说什么?好吧,SO的一位成员曾经给我传递了“Python的Zen”,而该文档中的一些摘录包含了一些Python的核心理念,比如“可读性计数”,“简单比复杂好”,而且{}我强调最后一个摘录是有原因的。在

下面是一个抽象编程语言的例子,有一个char类型:SML。以我在交互模式下的两个陈述为例:

- val a = "a"
val a = "a" : string    #interpreter type feedback

- val a = #"a"
val a = #"a" : char     #interpreter type feedback

在上面的两个例子中,我有两种方法来表示一个人类可读的字符,尽管它们本质上是不同的类型。虽然以今天的标准来看,SML是一种相对抽象的语言,但它的核心理念在于计算、数学表达语法和bug安全性。最后一点对于纯功能语言来说更是如此。因此,尽管抽象强调要远离低级语言的可怕细节,但它仍然不像Python这样的语言那样强调“可读性”和“易用性”。在

事实上,脚本语言通常强调快速生成代码,以及易于学习和使用的语法。就Ruby而言,松本甚至宣称这种语言应该“使用起来很有趣”。基本上,在我最谦虚的估计中,我认为在Python这样的语言中不区分char和string数据类型的原因是简单的概念。冗长和复杂似乎是脚本语言的敌人。此外,最后一点,如果有人倾向于使用与C兼容的数据类型,那么Python有一个ctypes库。在

归根结底,语言设计者就是这样决定的。很难再进一步了。在

然而,关于C的一点,它通常被认为是一种低级语言,因为它的语法更准确地反映了正在执行的数据和任务的性质。把一个字符当作一个字符串来处理是一个抽象的层次,这是C语言所不具备的特征,它会使我们不太清楚数据在背后是什么样子的。当你只需要一个角色时,它几乎肯定会增加开销。在

请注意,C类型语言确实支持单字符字符串,因此在我看来,这两种语言都是最好的。在

相关问题 更多 >