【问题标题】:Where is the new Object of String created when we concat using + operator我们使用 + 运算符连接时创建的 String 的新对象在哪里
【发布时间】:2018-11-11 04:20:27
【问题描述】:

我知道这可能非常基本,也可能非常简单,但我无法清楚地理解在这种情况下会发生什么,所以,就这样吧。

在以下代码中:

String str1 = "Hello";
String str2 = "World";
String str3 = new String("HelloWorld");
String str4 = str1 + str2;

我知道 str1 和 str2 将分别在 字符串常量池内部创建一个对象“Hello”和“World”。而对于 str3,字符串常量池创建了一个新对象,该对象指向内部创建的“HelloWorld”字符串常量池

我的问题是,如果我连接 2 个或更多字符串(使用 '+' 或 concat() 方法)会发生什么?

会像 String str3 一样在 外部 池中创建一个新对象,还是将 str4 直接指向对象“HelloWorld”内部 字符串常量池

PS : IF 的情况类似于在池外部创建新对象,那么不使用关键字?

【问题讨论】:

标签: java string string-concatenation


【解决方案1】:

首先String s = new String("abs"); 它将创建两个对象,一个在池区域中,另一个在非池区域中,因为您使用 new 和字符串文字作为参数。

String str1 = "Hello";
String str2 = "World";
String str3 = new String("HelloWorld");
String str4 = str1 + str2;

到目前为止,您有五个字符串对象,四个在字符串常量池中,一个在堆中。所以你的 str4 完全是字符串池中的一个新对象, 也请检查以下代码,

 String str5="HelloWorld"; //This line will create one more String Constant Pool object because we are using the variable name as str5.
 String str6="HelloWorld";////This line will not create any object, this will refer the same object str5.

用于测试

System.out.println(str3==str4); //false
System.out.println(str4==str5);//false
System.out.println(str5==str6);//true

【讨论】:

  • 能否请您重新检查一下 str4 的创建位置。我认为它将在堆区域中创建,因为 str1 + str2 是运行时操作。请在下面的页面上查看我的完整评论。
【解决方案2】:

首先,这不是一个答案,这是你自己得到答案或解释情况的方法。
两个字符串的连接总是会创建一个新的字符串对象。
为了符合这件事,你可以做一件事,它是如何在内存堆和池中管理的。

1:转到 NetBeans:
2:编写这样的程序:

public class StringTest {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "World";
        String str3 = new String("HelloWorld");
        String str4 = str1 + str2;
        String str5 = str1 + str2;
        String str6 = str1.concat(str2);

        String str7 = "HelloWorld";
        String str8 = "HelloWorld";

        System.out.println("");
    }
}

3:只需在System.out.println(""); 这一行设置一个断点即可。
4:现在调试这段代码。
5:进入变量窗口(Window->Debugging->Variables),如下图:

6:现在右键单击str8 并选择Mark Object... 并为该对象添加一些标签,例如Same Object

现在您可以看到str7 上也出现了相同的标记行,例如:

这表明两个引用 str7' andstr8` 是引用同一个对象。

7:现在检查这个东西是否有str3-4-5-6 所有引用,方法是用不同的标记行标记它们:

要进一步对该对象进行内部管理,只需在变量窗口中右键单击变量名称,查看Show Refereances 选项,例如:

更新:
- 串联在堆中创建对象。
- 确保此语句 look 表示池不能包含具有相同值的多个字符串
- 这里str7-8 是来自池的引用对象,与第 7 点的屏幕截图中所描绘的str4-5-6 不同。
- 您还可以通过使用== 运算符将str5str7 进行比较来确认它,如果它返回true,则连接会在池中创建对象,因为 str7 引用池,两者都引用同一个对象,但它会返回 false,因为两者不相同。

【讨论】:

  • "两个字符串的连接总是创建一个新的字符串对象。" 在游泳池内还是在游泳池外
【解决方案3】:
        **str4 is stored in heap.**        
                String str1 = "Hello";
                String str2 = "World";
                String str3 = new String("HelloWorld");
                String str4 = str1 + str2;
                String str5="HelloWorld";
            if str4 is stored on string pool then str5 will point to same object where str4 is pointing.
            but this statement giving me false output-:
                **System.out.println(str4 == str5);**
            ***************output****************
            false

                 String str4 = (str1 + str2).intern();
                 String str5="HelloWorld";
                but if you are using  String.intern then this method will try to find a String with the same sequence of characters in the pool.
    **System.out.println(str4 == str5);**
    ***************output******************
    true


  [1]: https://i.stack.imgur.com/IjMhP.png

【讨论】:

    【解决方案4】:

    为了回答您的问题,在池外创建了 str4 对象。

    这是我的解释:

        String s = "abc";
        String s1="xyz";
    
        String s3 = "abcxyz";
        String s2=s+s1;
    
        if(s2 == s3){
            System.out.println("true");
        }else{
            System.out.println("false");
        }
    

    这将打印错误。这意味着 s2 不是指由 s3 创建的池对象。

    【讨论】:

      【解决方案5】:

      在阅读我的 cmets 之前,请记住两点。

      1. 连接期间任何运行时操作的结果都会在堆区创建对象。
      2. intern() 方法从字符串常量池 (scp) 区域获取引用。

      现在,

      String s = "you";       // s in scp
      String s1 = s + "me";   // "me" in scp and runtime operation here will put s1 in heap
      String s2 = "youme";    // s2 in scp
      

      要确定我上面的观点,请参见下面的代码。

      System.out.println(s1 == s2);          // false , since s1 is in heap and s2 is in scp
      System.out.println(s1.intern() == s2); // true , since s2 in scp and s1.intern() in scp
      

      有没有像下面这样的。

      String s3 = "you" + "me"; //operation is compile time now, s3 in scp
      

      所以,

      System.out.println(s3 == s2); // true, s3 in scp and s2 in scp
      

      注意:String的“abc”值是编译时常数

      【讨论】:

        猜你喜欢
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        相关资源
        最近更新 更多