Java类型转换。背后的逻辑(String),. toString()和"" + int

时间:2016-05-19 16:17:31

标签: java string casting tostring

Java是一种强类型语言。因此,编译代码中的错误更少,编码速度更慢,可读性更高。因此,需要显式类型转换,这部分是清楚的。

这些片段之间有什么区别:

(String)myInt // obviously doesn't compile
Integer.toString(myInt)
"" + myInt

这纯粹是出于历史原因,还是背后有一些含义? 哪种方法合适?

5 个答案:

答案 0 :(得分:5)

如前所述,(String) myInt是一种类型转换。您可以在对象层次中在基元内或向上投射。由于int是基元,String是对象,因此我们遇到了问题。即使Autoboxing无法解决这种困境,因为IntegerString并不代表继承关系。因此,(String) myInt导致编译错误是完全合理的。

Integer.toString(myInt)"" + myInt的语义相同。然而,细节是不同的。

执行Integer.toString(myInt)时,会构造一个新的String,其中包含myInt的字符串表示。

执行"" + myInt时,首先构造一个全局String - 常量,其值为""(这是由JVM完成的,你看不到这个 1 < / SUP>)。词法分析器在String的右侧需要+,因为它找到了String左侧的+。对于原语,JVM&#34;知道&#34;如何将它们转换为String s。对于对象,调用toString()。由于Object具有此方法,并且每个类(至少是隐式)派生自Object,因此每个对象都保证具有toString()方法。这是构建的第二个String。从Strings are immutable开始,JVM可能会创建第三个String,表示前两个String s 2 的串联。

尾声:
然后,在执行时,JIT编译器会发生冲击,并且大多数情况可能无关紧要,因为两种变体的JIT优化版本可能看起来相同。或不。或者可能只是有时候。 JIT做有趣的事情。所以最后它更多的是个人风格而不是表现的问题:)

1 这实际上是一个谎言。写作时

String s1 = "";
String s2 = "";
System.out.println(s1 == s2);

人们会发现结果是true,而false是预期的。这是因为JVM为所有String常量创建了一个池来节省一些内存。

2 很有可能JVM&#34;识别&#34; something + "" == "" + something == something,因此不会创建第三个String。我既没有测试也没有研究过这个。

答案 1 :(得分:4)

我倾向于选择String.valueOf(int),我自己,但是有多条路可以到达那里。

一般情况下,如果您要将int转换为String 隔离,则需要Integer.toString(int)String.valueOf(int),或类似的。

您的"" + myInt效率明显低于上述效果(虽然通常无关紧要):它会编译为创建新的StringBuilder,然后将""附加到其中,然后将int附加到它(它调用上述方法之一将其首先转换为字符串),然后从String获取StringBuilder。因此,虽然您可以将其作为整体连接操作的一部分,但它本身很差。

您的(String)示例无效:您无法将int投射到String,您将获得编译时间& #34;不兼容的类型&#34;错误。

答案 2 :(得分:3)

这是一种正式的语言功能&#34;重载"" + myInt 运算符,使

new StringBuilder().append("").append(myInt).toString();

编译就像是:

StringBuilder#append()

String.valueOf()(最终)调用myInt来呈现{{1}}。

这个功能大概是因为如果他们没有,没有人会使用这种语言 - 那就太痛苦了。

答案 3 :(得分:2)

(String) - 这只适用于字符串,所以如果你有这个:

Object test = "test";
String test2 = (String) test;

它会起作用(因为Object测试将是String类型)。

如果你有这样的事情:

Integer test = new Integer(2);
String test2 = (String) test;

你得到ClassCastException

Integer.toString(myInt)

这就是它的作用:

 public static String  toString(int i) {
         if (i == Integer.MIN_VALUE)
             return "-2147483648";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
         char[] buf = new char[size];
         getChars(i, size, buf);
         return new String(0, size, buf);
     }

它只是通过char将你的号码变成字符串char。

"" + myInt

这将告诉编译器你想要将字符串连接起来,而不是添加两个数字(因为字符串是第一个,它将与连接字符串一起使用)。 myInt将变为字符串,或者如果它是一个对象,它将从中调用toString()方法。

另外,请务必阅读JVM中的字符串池,了解它将在此处执行的操作。在这种情况下,最终可能会创建大量临时字符串(如果您有很多+;请使用StringBuilder来避免这种情况。)

答案 4 :(得分:2)

首先,让我们比较(String)valval.toString()

这两个陈述的主要区别在于,编译器进行强制转换,而toString()方法通常由程序员实施。也就是说,只有在值String延伸且您可以实现任何类的toString()时才能进行强制转换。 toString()就像任何其他方法一样,没有任何(几乎)特别的方法。

现在让我们来看看""+int。我个人认为这是反模式,因为它被编译成非常低效的代码。创建了许多无用的对象;简而言之:结果类似于手动连接几个字符串文字与StringBuilder。此外,在""+var var这样的语句中,String不会扩展toString(),而是隐式调用 public static void main(String[] args) { int i= (int) getValue(10,int.class); System.out.println("int value -->"+i); Double d = (Double) getValue(25.023,double.class); System.out.println("double d-->"+d); String s=(String) getValue("adf",String.class); System.out.println("String s-->"+s); } public static <T> Object getValue(Object obj,Class<?> type) { return obj; }

我希望这很清楚。