开发者社区 问答 正文

Java(C#)String类型有什么不同

screenshot
第一个与第二个结果为什么会false?
第三个是2个字符串直接拼接会在常量池中生成新的对象(当对象已存在时候直接返回对象地址),所以str的指向的对象和字符串拼接结果所指向的对象是相同的,不知道这种理解是否有问题?
screenshot
然而C#中的结果都为true,这2种语言对string类型的维护上有什么不同?求大神解答

展开
收起
蛮大人123 2016-02-25 14:28:09 2949 分享 版权
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

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

    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表示将栈顶引用型数值存入指定本地变量
    那么
    screenshot
    表示 abc 在运行时常量池中间取出,并且将引用赋给str变量。
    同理,str1,str2都一样。
    那么这就说明一个问题:
    类似于String str1="dddd"说明"dddd"字符串存在运行时常量池中,而不是存在堆中间。
    然后看s2+s3:
    screenshot
    java运算符重载了加法。也就是字符串的加号是通过StringBuilder的append和toString来完成的。查看toString的源码:
    screenshot
    很显然是新生成了一个String,引用地址不一样,那么"=="判断当然为false。
    然后看
    screenshot
    screenshot
    说明,对于这种情况,java编译器做了优化。直接存储在运行时常量池中间。那么当然为true。

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

    2019-07-17 18:47:30
    赞同 展开评论
问答分类:
问答地址: