为什么 new String("") 编译通过而 char c = '' 不通过?

54
为什么空字符串是有效的而空字符不是? 我本以为空字符串不是字符串,只是一个占位符。对于char同样如此,但创建一个空的char甚至无法编译。
我想知道的是为什么会出现以下情况 - 可以编译 -
String s = "";

无法编译 -

char c = '';

20
如果你的例子有编译通过,你会期望变量 c 具有什么值? - Gabe
15
事实证明,你不能拥有一个没有值的 char。就像 intdouble 一样,char 必须始终具有某个值。 - Gabe
4
如果需要一个特殊的“没有字符”值,你可以将一个Character对象设置为null。 - kapex
9
Java 不是 C++,不要用 new String("") 来初始化字符串,这会导致创建两倍的字符串。如果你想要一个空字符串,应该将它们初始化为 "",例如:String example = ""。 - DwB
3
ASCII码中的0可以表示为'\0' - Callum Rogers
显示剩余4条评论
13个回答

119
因为char表示单个字符,而''并不是。一个字符串可以包含零个或多个字符,但是字符只能是单个字符。

8
好的,这就像把一个整数设为..什么也不是。 - Jørn Jensen
实际上,我曾经认为编译器会将变量初始化为(字面上的)0,这在任何编码中都不是字符。我以为... - Andrew J. Brehm
12
@Andrew:字符0是一个字符。具体来说,它被称为NUL'\0' - Matthew Scharley
完全有道理。很好。+1 - Tarik
2
@AndrewJ.Brehm:当然,语言设计者本可以将''等同于'\0',但他们选择不这样做,可能是因为这会导致一小部分持续的问题,例如“在Java中,''代表什么?” - Marcelo Cantos
显示剩余3条评论

34
因为字符串字面量代表一个可以由零个或多个字符组成的字符串,而(有效的)字符字面量则代表恰好一个字符。

char可以定义为一种可以存储0或1个字符的数据类型...

是的。理论上它可以被定义为这样的数据类型。但是请相信我,如果你认真考虑所有问题(例如如何表示空字符,应用程序如何处理它等等),你会得出结论,其中有很少的好处,但有显著的缺陷。
无论如何,仅仅为了保持String和char字面量之间的语法一致,而这么做的话,那就完全疯了。你不会因为语法看起来漂亮,就破坏语言的性能和/或语义。
在接受的答案的评论中,有人提出''应该与'\0'具有相同的含义。但是对此的反驳是'\0'并不意味着没有字符,它意味着一个值为零的字符。因此,如果''实际上意味着一个字符,那么这是误导的。而且,既然已经有一种表示方法...即'\0'...那么第二种表示方法就是多余的。
如果某个新的语言语法既具有误导性又是多余的,那么很难去证明需要添加它。
回应SoloBold的评论,虽然可以定义一种字符类型来实现这一点,但它将需要更多的空间。至少是1个比特,更可能是16个比特,以避免令人尴尬的内存对齐问题。32位的char类型是不可接受的...即使它可以解决其他问题。

换句话说,这是一个设计/定义决策。char可以被定义为一种可以存储0或1个字符的数据类型,但它并没有被定义成那样。这也许是好事,因为空的char没什么用处。 - wprl
1
@wprl - 一个更实际的原因是这样做是个坏主意,因为要么“窃取”一个char值来表示“没有字符”的情况,要么扩大char的大小以腾出空间来标记“没有字符”。 - Stephen C

13

""是一个空字符数组。

''只是没有字符。


8
一个空字符串就像一个什么也没有的容器。一个char必须有一个值,而没有一个确切的字符,就无法从中派生出该值。

5

您可以将字符串视为字符序列。有一个没有字符的空序列是有意义的,但有一个不是字符的字符是没有意义的。

此外,永远不要使用String s = new String("");,只需要String s = ""就足够了。


4

char是一种原始类型,因此您需要给它赋一个值(无论是什么)。 如果您想将变量保留为“未定义”,可以使用包装对象:

Character c = null;

这样,你的变量 c 目前并不包含任何值。但是一定要确保添加一个值! :)


4

从数学上讲,字母表A是一组符号,假设字母表A = {a,b,c,d,...,z}。字符串L是来自字母表中的零个或多个字符的序列,即L = A*。空串只是零个字符的序列;而“空字符”不是字母表的成员。

你不能有一个空字符,这是不合逻辑的。


2

顺便提一下,你可以使用对象包装器来处理原始的char类型:

Character c = null;
Character c2 = 'a';

这在您希望一个字段是“字符或空”时非常有用。

2
String s = null;              // OK
String s = new String("");    // OK
String s = new String("A");   // OK
String s = new String("ABC"); // OK

char c = 'A';                     // OK
char c = '';                      // NOT OK!
Character c = null;               // OK
Character c = new Character('A'); // OK
Character c = new Character('');  // NOT OK!

1
正如其他人所指出的,这里不需要使用 new 关键字,实际上会导致每种情况下创建 2 个对象;一个是 "A" 部分的对象,另一个是基于/复制自 "A"new 部分的对象... - johnny
我使用了new String()来使它看起来与new Character()相同,并明确表明Character是一个对象,而char不是。 - Giorgio

0
可能是因为char是一种原始类型,而String是一个对象。 boolean、int等也不允许“空”值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接