为什么没有字符串。Java是空的?

我知道,每次键入字符串字面值""时,字符串池中都会引用相同的string对象。

但是为什么字符串API不包括public static final String Empty = "";,所以我可以使用String.Empty的引用?

它至少可以节省编译时间,因为编译器知道要引用现有的String,而不必检查它是否已经被创建以供重用,对吗?就我个人而言,我认为字符串字面量的激增,尤其是微小的字符串,在很多情况下是一种“代码气味”。

所以在没有绳子的背后有一个伟大的设计原因。是空的,还是语言的创造者根本不同意我的观点?

446879 次浏览

String.EMPTY是12个字符,而""是2个字符,它们在运行时都将引用内存中完全相同的实例。我不完全确定为什么String.EMPTY会节省编译时间,事实上我认为是后者。

特别是考虑到__abc0是不可变的,它不像你可以先得到一个空字符串,并对它执行一些操作-最好使用StringBuilder(或StringBuffer如果你想线程安全),并将其转换为String。

< p > 更新 < br > 从你对问题的评论:

是什么激发了这个 TextBox.setText(""); < / p >

我相信在适当的类中提供一个常量是完全合理的:

private static final String EMPTY_STRING = "";

然后在代码中引用它

TextBox.setText(EMPTY_STRING);

通过这种方式,至少你明确了你想要一个空字符串,而不是你忘记在你的IDE中填充字符串或类似的东西。

所有这些""字面量都是同一个对象。为什么要制造那么多额外的复杂性呢?它只是输入的时间更长,更不清楚(编译器的成本是最小的)。由于Java的字符串是不可变的对象,因此根本不需要区分它们,除非可能是为了提高效率,但对于空字符串字面值来说,这不是什么大问题。

如果你真的想要一个EmptyString常量,你可以自己创建。但这样做只会鼓励更冗长的代码;这样做会有任何好处。

< p > 我知道,每次我输入String字面值“”,相同的String对象在String池中被引用。 < br > 没有这样的保证。你不能在你的应用程序中依赖它,这完全由jvm决定 < p > 或者语言的创造者只是不同意我的观点? < br > 是的。对我来说,这似乎是非常不重要的事情

Apache StringUtils也解决了这个问题。

其他方案的缺点:

  • isEmpty() -非空安全。如果 string为空,抛出NPE
  • length() == 0 -同样不是空安全的。 也没有考虑到 空格的字符串。李< / >
  • 与EMPTY常量的比较- 5月 不是空安全的。李空格问题< / >

Granted StringUtils是另一个可以拖动的库,但它工作得非常好,节省了大量的时间和检查空值或优雅地处理npe的麻烦。

为了补充Noel M所说的内容,您可以看看这个问题,这个答案表明常数是被重用的。

http://forums.java.net/jive/message.jspa?messageID=17122

字符串常量总是“被拘禁” 所以真的不需要这样 常数。< / p >

String s=""; String t=""; boolean b=s==t; // true

如果你真的想要一个字符串。EMPTY常量,你可以在你的项目中创建一个名为“Constants”(例如)的实用程序静态final类。这个类将维护你的常量,包括空String…

在同样的思想中,你可以创建ZERO, ONE int常量…在Integer类中不存在,但就像我评论的那样,写和读都很痛苦:

for(int i=Constants.ZERO; ...) {
if(myArray.length > Constants.ONE) {
System.out.println("More than one element");
}
}

等。

如果你想与空字符串比较而不担心空值,可以执行以下操作。

if ("".equals(text))

最终,你应该做你认为最清楚的事情。大多数程序员认为""意味着空字符串,而不是某人忘记输入任何内容的字符串。

如果您认为存在性能优势,则应该对其进行测试。如果你认为它不值得自己测试,那就说明它真的不值得。

对你来说,这听起来像是在试图解决一个在15年前设计该语言时就已经解决的问题。

对于那些声称""String.Empty是可以互换的或者""更好的人,你错了。

每次你做myVariable = "";您正在创建对象的实例。 如果Java的String对象有一个空的公共常量,那么只有一个对象实例""

如:-

String.EMPTY = ""; //Simply demonstrating. I realize this is invalid syntax


myVar0 = String.EMPTY;
myVar1 = String.EMPTY;
myVar2 = String.EMPTY;
myVar3 = String.EMPTY;
myVar4 = String.EMPTY;
myVar5 = String.EMPTY;
myVar6 = String.EMPTY;
myVar7 = String.EMPTY;
myVar8 = String.EMPTY;
myVar9 = String.EMPTY;

10个(11个包括String.EMPTY)指向一个对象

或:-

myVar0 = "";
myVar1 = "";
myVar2 = "";
myVar3 = "";
myVar4 = "";
myVar5 = "";
myVar6 = "";
myVar7 = "";
myVar8 = "";
myVar9 = "";

10个指针指向10个对象

这是低效的,在一个大型应用程序中,可能是非常重要的。

也许Java编译器或运行时足够高效,可以自动将“”的所有实例指向同一个实例,但也可能不是这样,需要进行额外的处理才能确定。

使用org.apache.commons.lang.StringUtils.EMPTY

不要只是说“字符串的内存池以字面形式重用,大小写封闭”。编译器在底层做什么并不是这里的重点。这个问题是合理的,特别是考虑到它所获得的赞成票数。

这是关于对称的,没有它,api对人类来说更难使用。众所周知,早期的Java sdk忽略了这条规则,现在为时已晚。下面是我想到的一些例子,你可以随意加入你最喜欢的例子:

  • BigDecimal。0,但没有AbstractCollection。空的,字符串。空
  • 数组中。List.size()
  • List.add() Set.add()但是Map.put() ByteBuffer.put()还有不要忘了StringBuilder.append() Stack.push()

回答得晚了,但我认为它为这个话题增添了一些新的内容。

之前的答案都没有回答最初的问题。一些人试图证明缺乏常数的合理性,而另一些人则展示了我们可以处理缺乏常数的方法。但是没有人能提供一个令人信服的理由证明常数的好处,所以它的不足仍然没有得到适当的解释。

常量是有用的,因为它可以防止某些代码错误被忽略。

假设您有一个大型代码库,其中包含数百个对“”的引用。有人在滚动代码时修改其中一个,并将其更改为“”。这样的更改很有可能在生产中不被注意到,在这一点上,它可能会导致一些问题,其来源将难以检测。

OTOH,一个名为EMPTY的库常量,如果遇到相同的错误,将为EMPTY之类的东西生成编译器错误。

定义自己的常数更好。有人仍然可能错误地更改其初始化,但由于其广泛使用,这种错误的影响比单一用例中的错误更难被忽视。

这是使用常量而不是文字值的一般好处之一。人们通常会意识到,在许多地方使用一个常量可以让您在一个地方轻松地更新该值。很少有人认识到的是,这也可以防止该值被意外修改,因为这样的更改会显示在所有地方。所以,是的,""比EMPTY短,但是EMPTY比""更安全。

因此,回到最初的问题,我们只能推测,语言设计者可能没有意识到为经常使用的文字值提供常量的好处。希望有一天我们能看到在Java中添加字符串常量。

这似乎是显而易见的答案:

String empty = org.apache.commons.lang.StringUtils.EMPTY;

很棒是因为“空初始化”;代码不再有“魔法字符串”;并使用一个常数。