【问题标题】:Why Char is actually a NumericType in Java, but not a SymbolicType or String?为什么 Char 实际上是 Java 中的 NumericType,而不是 SymbolicType 或 String?
【发布时间】:2015-11-10 02:46:04
【问题描述】:

关于Java语法,有一个NumericType,它由IntegralTypeFloatingPointType组成。 IntegralType 为 byteshortintlongchar

同时,我可以将单个字符分配给char 变量。

char c1 = 10;
char c2 = 'c';

所以这是我的问题。为什么是数字类型的 char 以及 JVM 如何将 'c' 转换为数字?

【问题讨论】:

  • 因为 ASCII 表(或 Java 中的 unicode)。每个字符都可以转换为数字,实际上所有数据都是由数字组成的,大多数语言中的编程标准都是将字符实现为数字(例如在 C 和 C++ 中,字符是字节,它们没有字节类型)。字母“c”在 ASCII 中将变为 99。
  • 不,伙计们,Java 中的chars 不是 ASCII。

标签: java


【解决方案1】:

除了能够对有时派上用场的字符进行算术运算(例如c >= 'a' && c <= 'z')之外,我会说这是一个设计决策,由发明 Java 时其他语言(主要是 C 和 C++)采用的类似方法驱动。

Character 没有扩展 Number(就像其他数字原语包装器所做的那样)这一事实在某种程度上表明 Java 设计人员试图在字符的数字和非数字性质之间找到某种折衷。

免责声明我找不到任何关于此的官方文档。

【讨论】:

  • 当然,如果将 char 定义为专门用于字符的非数字类型,他们可以定义 >=<=+- 这样他们以char 特有的方式工作(如字符串和+)。它只是使事情过于复杂。 :-) 不太清楚charCharacter 之间的“稍后”是什么意思,但我认为Character 不会扩展Number(而且我们一直都有拳击类型)。发现 JDK 1.0.2 reference 表明它没有。 :-) 尽我所能。
  • 真的,我的错,我没有表达清楚。我编辑了答案;谢谢你的评论。
【解决方案2】:

为什么是数字类型的字符...

使用数字将字符表示为表格的索引是计算机处理文本的标准方式。它被称为character encoding,历史悠久,至少可以追溯到电报。很长一段时间以来,个人计算机都使用 ASCII(7 位编码 = 127 个字符加上 nul),然后是“扩展 ASCII”(各种形式的 8 位编码,其中“高位”128 个字符有多种解释),但是由于字符集有限,这些现在已经过时并且仅适用于小众用途。在个人计算机之前,流行的是 EBCDIC 及其前身 BCD。现代系统使用Unicode(通常通过存储它的一个或多个transformations,例如UTF-8 或UTF-16)或各种标准化的“代码页”,例如Windows-1252ISO-8859-1

...以及 JVM 如何将 'c' 转换为数字?

Java 的 numeric char values 通过 Unicode 映射到字符和从字符映射(这是 JVM 知道 'c' 是值 0x0063 或 'é' 是 0x00E9 的方式)。具体来说,char 值映射到 Unicode 代码点,字符串为 sequences of code points

char 数据类型有很多内容,包括为什么值是 16 位宽,在 JavaDoc of the Character class

Unicode 字符表示

char 数据类型(以及 Character 对象封装的值)基于原始 Unicode 规范,该规范将字符定义为固定宽度的 16 位实体。此后,Unicode 标准已更改为允许表示需要超过 16 位的字符。合法代码点的范围现在是 U+0000 到 U+10FFFF,称为 Unicode 标量值。 (参考Unicode标准中U+n符号的定义。)

从 U+0000 到 U+FFFF 的字符集有时称为基本多语言平面 (BMP)。码位大于 U+FFFF 的字符称为补充字符。 Java 平台在 char 数组以及 String 和 StringBuffer 类中使用 UTF-16 表示。在此表示中,补充字符表示为一对 char 值,第一个来自高代理范围 (\uD800-\uDBFF),第二个来自低代理范围 (\uDC00-\uDFFF)。

因此,char 值表示基本多语言平面 (BMP) 代码点,包括代理代码点或 UTF-16 编码的代码单元。一个 int 值表示所有 Unicode 代码点,包括补充代码点。 int 的低(最低)21 位用于表示 Unicode 代码点,高(最高)11 位必须为零。除非另有说明,否则关于补充字符和代理字符值的行为如下:

  • 只接受 char 值的方法不支持补充字符。它们将代理范围中的 char 值视为未定义字符。例如,Character.isLetter('\uD840') 返回 false,即使此特定值后跟字符串中的任何低代理值将表示一个字母。

  • 接受 int 值的方法支持所有 Unicode 字符,包括补充字符。例如,Character.isLetter(0x2F81A) 返回 true,因为代码点值表示一个字母(CJK 表意文字)。

在 Java SE API 文档中,Unicode 代码点用于 U+0000 到 U+10FFFF 范围内的字符值,Unicode 代码单元用于 16 位字符值,它们是 UTF- 16 位编码。有关 Unicode 术语的更多信息,请参阅 Unicode 词汇表。

【讨论】:

  • 这真的是一个全面的解释与有用的链接。但是,我仍然不明白它是如何回答这个问题的。例如,使用数字作为布尔表达式也是编程语言的标准方式(0false,而不是 0true)。但是,您不能在 Java 中将 int 分配给 boolean。如果char 是像boolean 这样的非整数类型会有什么伤害(除了提供更好的类型安全性)?至少编译器会将以下代码报告为无效,而不是让它在运行时打印bnew StringBuilder('a').append('b').toString()。 :)
  • @DraganBozanovic:“为什么”语言设计问题总是很棘手,归结为“因为设计师就是这样做的”。 :-) 我认为在这种情况下,能够对char 值进行数学运算的实用性被认为足够有用,使它们成为数字具有明确的价值,并且对boolean 值进行数学运算并没有明确的价值。但归根结底,人们真的不得不问詹姆斯·高斯林(或者找到他过去回答过这个问题的地方)。 :-)
  • 我的想法类似;感谢您的澄清。
【解决方案3】:

在内部char 存储为整数的 ASCII(或 UNICODE)代码。区别在于从内存中读取后的处理方式。

在 C/C++ 中,charint 非常接近,并且是隐式类型转换的。 Java 中的类似行为显示了 C/C++ 和 Java 之间的关系,因为 JVM 是用 C/C++ 编写的。

【讨论】:

    【解决方案4】:

    因为在 Java 中将字符表示为 Unicode。这样做有一些便利,例如,您可以运行从“A”到“Z”的循环并做一些事情。然而,重要的是要意识到,在 Java 中,字符串并不像在某些其他语言中那样严格地是字符数组。更多信息here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多