首页 > Java(C#)String类型的比较

Java(C#)String类型的比较

javaString str = "abc";
String str2 = "a";
String str3 = "bc";
System.out.println(str == str2 + str3);     //fasle
System.out.println(str == "a" + str3);      //fasle
System.out.println(str == "a" + "bc");      //true

第一个与第二个结果为什么会false?
第三个是2个字符串直接拼接会在常量池中生成新的对象(当对象已存在时候直接返回对象地址),所以str的指向的对象和字符串拼接结果所指向的对象是相同的,不知道这种理解是否有问题?

string str = "abc";
string str2 = "a";
string str3 = "bc";
Console.WriteLine(str == str2 + str3);  //true
Console.WriteLine(str == "a" + str3);   //true
Console.WriteLine(str == "a" + "bc");   //true

然而C#中的结果都为true,这2种语言对string类型的维护上有什么不同?求大神解答


@沙渺 正解


分析一下字节码就知道了。

java// Compiled from StringDemo.java (version 1.5 : 49.0, super bit)
public class collections.StringDemo {

  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public StringDemo();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 6]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: collections.StringDemo

  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 5, Locals: 4
  public static void main(java.lang.String[] args);
     0  ldc <String "abc"> [16]
     2  astore_1 [str]
     3  ldc <String "a"> [18]
     5  astore_2 [str2]
     6  ldc <String "bc"> [20]
     8  astore_3 [str3]
     9  getstatic java.lang.System.out : java.io.PrintStream [22]
    12  aload_1 [str]
    13  new java.lang.StringBuilder [28]
    16  dup
    17  aload_2 [str2]
    18  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [30]
    21  invokespecial java.lang.StringBuilder(java.lang.String) [36]
    24  aload_3 [str3]
    25  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39]
    28  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43]
    31  if_acmpne 38
    34  iconst_1
    35  goto 39
    38  iconst_0
    39  invokevirtual java.io.PrintStream.println(boolean) : void [47]
    42  getstatic java.lang.System.out : java.io.PrintStream [22]
    45  aload_1 [str]
    46  new java.lang.StringBuilder [28]
    49  dup
    50  ldc <String "a"> [18]
    52  invokespecial java.lang.StringBuilder(java.lang.String) [36]
    55  aload_3 [str3]
    56  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39]
    59  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43]
    62  if_acmpne 69
    65  iconst_1
    66  goto 70
    69  iconst_0
    70  invokevirtual java.io.PrintStream.println(boolean) : void [47]
    73  getstatic java.lang.System.out : java.io.PrintStream [22]
    76  aload_1 [str]
    77  ldc <String "abc"> [16]
    79  if_acmpne 86
    82  iconst_1
    83  goto 87
    86  iconst_0
    87  invokevirtual java.io.PrintStream.println(boolean) : void [47]
    90  return
      Line numbers:
        [pc: 0, line: 8]
        [pc: 3, line: 9]
        [pc: 6, line: 10]
        [pc: 9, line: 11]
        [pc: 42, line: 12]
        [pc: 73, line: 13]
        [pc: 90, line: 15]
      Local variable table:
        [pc: 0, pc: 91] local: args index: 0 type: java.lang.String[]
        [pc: 3, pc: 91] local: str index: 1 type: java.lang.String
        [pc: 6, pc: 91] local: str2 index: 2 type: java.lang.String
        [pc: 9, pc: 91] local: str3 index: 3 type: java.lang.String
}

现在一个个的分析:
ldc表示将int, float或String型常量值从常量池中推送至栈顶.
astore表示将栈顶引用型数值存入指定本地变量
那么

javaldc <String "abc"> [16]
     2  astore_1 [str]

表示 abc 在运行时常量池中间取出,并且将引用赋给str变量。
同理,str1,str2都一样。
那么这就说明一个问题:
类似于String str1="dddd"说明"dddd"字符串存在运行时常量池中,而不是存在堆中间。

然后看s2+s3:

javanew java.lang.StringBuilder [28]
    16  dup
    17  aload_2 [str2]
    18  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [30]
    21  invokespecial java.lang.StringBuilder(java.lang.String) [36]
    24  aload_3 [str3]
    25  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39]
    28  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43]

java运算符重载了加法。也就是字符串的加号是通过StringBuilder的append和toString来完成的。查看toString的源码:

java  public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

很显然是新生成了一个String,引用地址不一样,那么"=="判断当然为false。

然后看

java "a" + str3
javaldc <String "a"> [18]
    52  invokespecial java.lang.StringBuilder(java.lang.String) [36]
    55  aload_3 [str3]
    56  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [39]
    59  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [43]
    62  if_acmpne 69
    65  iconst_1
    ```
    不用看。既然是StringBuilder那么也一定是false了、


最后"a"+"bc"
```java
iconst_0
    70  invokevirtual java.io.PrintStream.println(boolean) : void [47]
    73  getstatic java.lang.System.out : java.io.PrintStream [22]
    76  aload_1 [str]
    77  ldc <String "abc"> [16]
    79  if_acmpne 86

说明,对于这种情况,java编译器做了优化。直接存储在运行时常量池中间。那么当然为true。

那么C#。。。。不知道他们运行机制是咋样的。


java 编译期将"a"+"bc"优化为"abc"了


http://stackoverflow.com/questions/767372/java-string-equals-versus
http://stackoverflow.com/questions/1659097/why-would-you-use-string-eq...


Java中String不是基本类型是对象啊


对于Java:

对于C#:

在这个问题上,C#的实现明显是更优的——常用操作简明,不常用操作啰嗦。从而程序编写上语义自然,不易出错。

【热门文章】
【热门文章】