x.toString()和x +“”之间的区别

回到大学我的一个教授。 教我们只做x + ""作为从基本类型到字符串的快速转换。
我不记得我在一些Java和C ++课程中使用过哪一堂课(我现在还没有使用过一段时间),但我现在在C#/ .Net中使用它,这就是我主要开发的内容在最近。

使用.toString() over +""对于int,decimal,float等基本类型是否有优势? 什么情况.toString()会更好?

注意:我也被显示.toString() ,教授刚推荐+""因为它更短,我从那时起就完成了,而没有质疑它。

好吧,作为旁注,它取决于x是什么。 如果x是Java中的原语,则必须使用其中一个包装器调用.toString()

Integer.toString(x)

我会说使用toString()通常更好,因为至少在Java中,x +“”表示你想要将两个字符串附加在一起。

就像在这个例子中:

  public static void main(String[] args) { int x = 3; String s = x + ""; } 

最终,在字节码中,如下:

 public static void main(java.lang.String[]); Code: 0: iconst_3 1: istore_1 2: new #2; //class java/lang/StringBuilder 5: dup 6: invokespecial #3; //Method java/lang/StringBuilder."":()V 9: iload_1 10: invokevirtual #4; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 13: ldc #5; //String 15: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 21: astore_2 22: return 

所以它必须创建一个StringBuilder来追加“”和x的String值。 虽然效率损失不是那么多,但使用toString函数并不算太多。

与使用toString比较:

  public static void main(String[] args) { int x = 3; String s = Integer.toString(x); } 

最终结果如下:

 public static void main(java.lang.String[]); Code: 0: iconst_3 1: istore_1 2: iload_1 3: invokestatic #2; //Method java/lang/Integer.toString:(I)Ljava/lang/String; 6: astore_2 7: return 

虽然它可能只是我的观点,但使用.toString反映了你真正想要的东西 – 你想要x的字符串值,而使用x +“”是一种破解并且说 – 我希望x的字符串值连接起来用“”。

旁注:我不能谈论C#会发出的中间字节码,但我想象一下类似的东西。 另外,使用C#,您可以像引用类型一样轻松地调用值类型的.ToString(),所以我认为我的建议也适用。

老实说,我认为这种奇怪的建议。

我不能说出每一个特定情况,但一般来说, x + ""在C#中会做什么(这应该取决于xstring类型的重载+运算符的存在)是类似string.Concat(x, "")调用string.Concat(x, "")反过来会调用x.ToString

在典型的情况下,这只意味着x + ""的开销比x.ToString多一个方法调用。 但是,当x是某个值类型的变量时,这也会导致x的值被加框,除非特别针对x的类型存在+的重载(这可能被认为是无用的点,因为x也会如果它的类型没有覆盖那个方法,则在调用ToString时装箱;这让我感到有点罕见,但最确定的确是这样。

当然,这些是相当微不足道的差异。 这两种方法的真正区别在于可读性; 根据我的经验, x + ""在.NET中不是很惯用,所以我倾向于避免它。 也就是说,它可能只是在我所居住的.NET世界中并不常见,而可能有很多.NET开发人员在那里做这件事。

指出的是,在Java中,也许你不得不为原始类型的变量x (如C)和C#以及.NET中的所有类型(包括所谓的“原始”类型Integer.toString(x)编写笨重的Integer.toString(x) 。 )inheritance自object ,因此可以使用ToString方法(以及GetTypeGetHashCode )。

在Java中,对于基本类型( intdouble等),您不能编写.toString()因为类型不是对象。 这意味着您的选择要么是要写类似的东西

 x + ""; 

或使用

 Integer.toString(x); 

在C ++中,你不能使用x + ""进行这种转换,因为这将被视为指针算术并且会给你一个坏指针。 使用boost::lexical_cast类的东西是进行转换的首选方式。

而且……我对C#一无所知,所以我不会评论它。 🙂

使用x+""没有任何优点或缺点。 toStringObject类型的方法,每次向string添加任何对象时都会隐式调用它。

如果您愿意,您始终可以在class级中覆盖此方法。

因为字符串是不可变的,所以x+""调用两个函数:x.toString()和StringBuffer.append()(至少在Java中)。 我想大多数好的JIT都会把它变成一个单独的函数调用x.toString(),但是如果不进行实际测试我就无法确定。

真的,没关系。 这不太可能导致任何性能问题。 所以它仍然是个人风格的问题。 使用您或您的团队所熟悉的任何内容。

在Java中

除了处理基本类型之外, x+""也适用于null 。 其中x.toString()抛出NullPointerExceptionx+""返回"null" 。 这是否更好取决于你,但这是一个区别。

在C#中,我会完全忽略这个建议,而是支持更具说明性的东西,例如直接使用.ToString

此语法为您提供的唯一潜在优势是,如果xnull ,它将创建一个空字符串。 如果这被认为是代码中的优势,我倾向于使用扩展方法。

 public static string NullSafeToString(this T value) where T : class { return value == null ? "" : value.ToString(); } 

避免这种情况的另一个原因是它可以造成优先混淆。 例如,如果不使用参考材料,您是否确切知道z在以下场景中的价值是什么?

 int x = 42; int y = 15; string z = x + y + ""; 

现在同样的问题如下

 int x = 42; int y = 15; string z = x + y.ToString(); 

对于没有花时间记忆C#运算符优先级的普通开发人员来说,后者更容易被一目了然。 因此我更喜欢它,因为它被误解的可能性较小。