简体   繁体   中英

Understanding explicit cast for String producing different results in c# and Java

I wrote a same(..similar?) piece of code for Java 7 and C#(.net 3.5) and got a confusing output. Please help me in understanding this behavior:

Java:

public class strTest {
    public static void main(String [] s) {      
        String s1 = "abc";
        String s2 = new String(new char[] {'a', 'b', 'c'});
        System.out.println(s1 == s2);                      // false
        System.out.println(((Object)s1) == ((Object)s2));  // false
        System.out.println(s1.equals(s2));                 // true
    }
}

Output : false false true

C#:

namespace ConsoleApplication1
{
    class Program2
    {
        static void Main(string[] args)
        {
            String s1 = "abc";
            String s2 = new String(new Char[] {'a', 'b', 'c'});
            Console.WriteLine(s1 == s2);                     // true
            Console.WriteLine(((Object)s1) == ((Object)s2)); // false
            Console.WriteLine(s1.Equals(s2));                // true
        }
    }
}

Output : True False True

I am aware of concepts like String immutability and String pool but I guess I am missing the finer print.

In java: Why did it create a new String object for s2 when it could have used the one which is referenced by s1? Isn't that what String pool is supposed to achieve?

There are two aspects to your question: when objects are created, and how == comparisons work:

Object creation

In terms of interning ("pooling") - only constants are interned automatically. You can intern other strings using Intern / intern , but when you just call the string constructor that will always create a new string. (Well, except for one bizarre corner case in .NET, but we can ignore that for now.)

So in your code, s1 and s2 always refer to different objects.

Comparison

The cause of the difference is your use of == . C# supports user-defined operator overloading, and String overloads it like this:

public static bool operator ==(string x, string y)

which compares the contents of the string rather than the references. So when you have two operands of type string , x == y ends up doing an equality comparison rather than an identity comparison. That's why the first line of the C# output is True .

Java doesn't have this behaviour, which is why is prints false .

When the operand types are Object , both C# and Java will use reference equality, which is why the second line is false in both cases.

I assume you are asking why C# says that s1==s2? String comparison compares the contents of two strings in a case sensitive manner. Since both strings have the same contents, their comparison returns true.

In Java only the string references are compared, to determine if the two variables refer to the same string. Their contents are not compared.

As for pooling, both Java and C# use pooling (interning in C#) for literals. Strings created programmatically result in new instances in both languages, even if a pooled instance already exist. Check the documantation of String.Intern for an example similar to yours, where the interned string is a different instance from the generated string even if their values are the same.

String pooling is used only with literals. If you say String s1 = "abc"; String s2 = "abc"; there will be just one object created.

The java language specification requires that when you use the 'new' keyword an actual new object is created, no cheating and returning an internal cached copy.

A new class instance is explicitly created when evaluation of a class instance creation expression (§15.9) causes a class to be instantiated.

Interning is applied to strings expressed as literals, but when you explicitly use the new key word, the language has to make you an actual new, different, object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM