在”传智播客DotNet面试宝典(改).pdf“有这样一道非常有意思,也比较有深度的题目。
String s = new String(“xyz”);创建了多少个String实例?
传智的老师告诉同学们:答案是两个,一个是”xyz”,一个是指向”xyz”的引用对象。
貌似很正确,很有道理。没错,”xyz”是一个字符串,而DotNet字符串(其实Java也是)有驻留intern这样一种机制。
抱歉的是,传智的老师没有料到,问这个问题的同学或者是公司太坏了。这道题的题目是错的,答案也不对。
大家手头有visualstudio的可以建立一个console程序试试看,能不能编译通过?!
至于答案为什么也不对,看看这篇非常详细的解释吧,虽然作者解释的是针对Java语言。
http://www.iteye.com/topic/774673
为什么Java能这样写?因为Java有这种构造函数String(String original)而DotNet中的String类没有。
稍微修改让它能够编译
static void Main(string[] args) { char[] chars = { 'w', 'o', 'r', 'd' }; String s2 = new String(chars); String s3 = new String(chars); int i = s2.Length; int j = s3.Length; Console.WriteLine(i + j); }
如果我们用ILSpy看,结果如下,注意,其中只调用了两次newobj,分别是针对s2和s3。
.method private hidebysig static
void Main (
string[] args
) cil managed
{
// Method begins at RVA 0x2058
// Code size 57 (0x39)
.maxstack 3
.entrypoint
.locals init (
[0] char[] chars,
[1] string s2,
[2] string s3,
[3] int32 i,
[4] int32 j
)
IL_0000: ldc.i4.4
IL_0001: newarr [mscorlib]System.Char
IL_0006: dup
IL_0007: ldtoken field int64 ‘<PrivateImplementationDetails>{06FAE1C3-0E45-4AE7-A401-B8A7D1EFF5D6}’::’$$method0x6000001-1′
IL_000c: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_0018: stloc.1
IL_0019: ldloc.0
IL_001a: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_001f: stloc.2
IL_0020: ldloc.1
IL_0021: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_0026: stloc.3
IL_0027: ldloc.2
IL_0028: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_002d: stloc.s j
IL_002f: ldloc.3
IL_0030: ldloc.s j
IL_0032: add
IL_0033: call void [mscorlib]System.Console::WriteLine(int32)
IL_0038: ret
} // end of method Program::Main