【问题标题】:What is the difference Between Assignment and Creating Instance of String? [duplicate]赋值和创建字符串实例有什么区别? [复制]
【发布时间】:2011-01-11 14:47:14
【问题描述】:

在一个面试问题中,面试官问我

以下说法有什么共同点和不同点:

String s = "Test";

String s = new String("Test");

内存分配有区别吗?

【问题讨论】:

标签: java string memory


【解决方案1】:
String s = "Test"; 

将首先在字符串常量池中查找字符串“Test”。如果 found s 将引用找到的对象。如果未找到,则创建一个新的 String 对象,将其添加到池中,并使 s 引用新创建的对象。

String s = new String("Test");

将首先创建一个新的字符串对象并让 s 引用它。此外,在字符串常量池中创建了字符串“Test”的条目,如果它还没有。

所以假设字符串“Test”不在池中,第一个声明将创建一个对象,而第二个声明将创建两个对象。

【讨论】:

  • 据我了解,常量池中的查找/对象创建发生在加载该类时,而不是执行该特定代码行时,该类代码中出现的所有文字。
【解决方案2】:

在记忆方面的区别在于形式的表达: String s = "test" 使用“interned”字符串来共享唯一实例。

表单的调用:String s = "test"
String s = new String("test")相比效率更高

第一次调用使用现有的常量表达式(如果有的话), 第二个调用创建一个新实例,而不使用任何现有实例。

下面的代码块演示了这一点:

String test = new String("test");
String internTest = "test";
String nonInternTest = new String("test");

System.out.println(test == internTest); // prints false
System.out.println(test != nonInternTest); // prints true
System.out.println(test.equals(nonInternTest)); // prints true

另请注意,JLS 指定行为如下:
每个字符串文字都是对 String 类实例的引用(第 4.3.3 节)。字符串对象有一个常量值。字符串字面量 - 或者更一般地说,作为常量表达式值的字符串是“内部”的,以便使用 String.intern 方法共享唯一实例。

【讨论】:

    【解决方案3】:

    第一个将在字符串池中搜索字符串文字“Test”,如果存在则 s 将引用该字符串并且不会创建新字符串。并且仅当“测试”字面量不存在时才创建新对象。

    但在第二种情况下,它将创建另一个对象,而无需过多考虑它是否存在。

    【讨论】:

      【解决方案4】:

      字符串 s = "测试"; // 创建一个String对象和一个引用变量 在这个简单的例子中,“Test”将进入池中,s 将引用它。

      String s = new String("Test"); // 创建两个对象和一个引用变量 在这种情况下,因为我们使用了 new 关键字,Java 将创建一个新的 String 对象 在普通(非池)内存中,s 将引用它。此外,文字“测试”将 放在游泳池里。

      但它们的共同点是它们都创建了一个新的 String 对象,带有一个 “Test”的值,并将其分配给引用变量s。

      【讨论】:

        【解决方案5】:

        +创建一个新的String对象和创建引用的区别只是我们告诉jvm创建一个新对象。 并创建引用意味着我们只创建我们自己的对象。

        【讨论】:

          【解决方案6】:
          String s=new String("Test")     
          

          在这种情况下,将在堆区域创建 2 个对象,另一个在 scp(字符串常量池)中,s 始终指向堆对象。

          String s ="Test";
          

          在这种情况下,scp 中只会创建 1 个对象,s 始终指向该对象

          注意
          1. 在 scp 中创建对象是可选的,首先它会检查 scp 中是否已经存在任何具有所需内容的对象,如果对象已经存在,那么现有的对象将被重用,如果对象不可用,那么只会创建一个新的对象。但这仅适用于 scp 而不适用于堆。

          2.垃圾收集器不允许访问 SCP 区域,因此即使对象不包含引用变量,如果它存在于 scp 区域中,它也有资格进行 GC

          所有的scp对象都会在jvm关闭的时候自动销毁。

          示例 2;

          String s1=new String("Test");
          String s4=new String("Test");
               String s2="Test";
               String s3="Test";
          

          注意:
          每当我们强制使用 new 运算符时,将在堆区域中创建一个新对象,因此可能存在 2 个在堆区域中具有相同内容但在 scp 中不存在的对象,即在堆区域中可能存在重复对象但不是在 scp 中。

          【讨论】:

            猜你喜欢
            • 2019-03-10
            • 2020-11-16
            • 2011-02-26
            • 2011-09-05
            • 1970-01-01
            • 2014-03-11
            • 2012-01-19
            • 2017-05-27
            • 2012-07-27
            相关资源
            最近更新 更多