将字符串定义为Null还是空字符串更好?

3

我来自C#.net的背景,每当我有一个字符串时,我都会声明为String.Empty。 现在我正在查看同事编写的Java代码,他在方法中声明字符串是这样做的:

String myStr = null;

我不喜欢这种做法,更糟糕的是,在“IF”块中为这些字符串分配值,可能甚至都不符合条件,然后在方法末尾调用myStr.length()

那么我的问题是,在Java中有什么更好的方式吗?你认为将它们定义为String.Empty还是保留它们作为null并在调用.length()之前进行null检查更好?


你是指 myStr = "";String.Empty 来代替吗? - Eng.Fouad
2
这不取决于你正在做什么吗?鉴于 nullempty 是不同的,它可以在流程中提供更多的选项。然而,一般来说,我发现最好不要使用 null,除非你必须使用它。 - davids
@Eng.Fouad:是的,一个空字符串。在.NET中,我们可以使用String.Empty,所以我只是习惯了那种语法,但是是的,那就是我想说的。 - Bohn
1
在声明时将局部变量赋值为null,然后在各种情况下重新分配它的模式是我经常看到的。这是一个糟糕的想法,因为它破坏了编译器检查它是否已被正确(“明确”)分配的能力。正如您所观察到的那样,它会让您面临NullPointerException的危险。我认为这是一个不可靠程序员的可靠标志! - Tom Anderson
关于在赋值时使用null的另一点,您可以放心地使用它,因为有许多工具(例如FindBugs、检查器框架)使用注释来检查NullPointerException的可能性,并在编译期间警告您。 - exexzian
4个回答

6
一般来说,使用null值是一个不好的想法,特别是当它们从方法返回或传递给另一个方法时。使用Null Object模式更好,在字符串的情况下,Null Object是一个空字符串。通过始终避免使用null,出现NullPointerException的可能性变得更小,代码变得更易读(这在Clean Code第7章110-112页中详细讨论)。
在Java中,String s = ""不会分配任何内存,因为JVM将对字符串文字进行了内部处理,所以甚至没有性能差异(即使有,也是一种过早的优化)。

1
空对象模式可以避免编译器流分析触发“变量未初始化”的警告,也可以避免使用哨兵,除非你能证明空对象不会出现在带内。 - user207421
@esko 说得对,但是 intern() 是 String 类的一个静态方法,因此使用它创建的字符串,包括 "" ,将永远不会被垃圾回收。 因此,使用 intern() 的成本将呈线性增长。 - exexzian
@EJP 噢,我的错误 - 是的,那个实习生不是静态方法。我看到了String.intern()并将其解释为静态方法。 - exexzian
@EJP,关于字符串常量的GC问题,请查看此链接http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html。 - exexzian
2
返回空字符串是一种代码异味的内部信号。如果一个方法的结果是“无”,那么null是适当的值。空字符串只是一个魔法值,对于那些太懒得进行null检查的人来说。 - Steve Kuo
显示剩余3条评论

4

两者都有用处。空字符串是内置的,即可以出现在输入中,因此它们并不能用作哨兵。Null仅作为哨兵有用。当你要追加时,你应该先初始化为空字符串。如果你马上要重新分配它,就不需要提供任何值,并且你应该将声明与重新分配结合起来。我经常看到这种情况:

String s = new String();
s = "some string";

这告诉我有人不理解这种语言。

在带内加1。如果一个方法的返回值是“无值”,那么null是适当的值。 - Steve Kuo

3

虽然两者都适用于不同场景,但把它赋值为null会更好(节省内存且容易出错),前提是你以后将某个字符串设置为该值,否则你将收到空指针异常。


2

一个空字符串通常意味着你应该使用StringBuilder(如果你正在添加字符串,这是一种常见情况)。null引用“更好”,因为它使用的内存更少,并且检查一个字符串是否为null比检查它是否为空要快。我建议不要使用空字符串代替将它们声明为null,尽管在使用之前你仍应该检查是否为null引用,除非你100%确定它在某个阶段已被赋值。


3
空字符串被存储在内部。拥有多个对空字符串的引用不会消耗任何内存。 - Mike Samuel
@paranoid +1 - 好观点,空字符串可用于与 StringBuilder 的 append 方法一起使用。 - exexzian
@exex 实际上,我的意思是空字符串经常在循环之前声明,然后使用 += 进行“追加”字符串。(不好的做法) - rtheunissen
@MikeSamuel 非常好的观点,感谢指出。+1 - rtheunissen

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