String s = new String("xyz");创建了多少个String实例?

在”传智播客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

发表评论