【问题标题】:How many object creates with new operator? [duplicate]使用 new 运算符创建了多少个对象? [复制]
【发布时间】:2011-07-09 09:08:49
【问题描述】:

可能重复:
Java Strings: “String s = new String(”silly“);”

如果我写

String s= new String("how many object b created by this method ");

与这样做相比,将创建多少参考对象和对象:

Sting s1="Is this method is good as compare to upper"; 

【问题讨论】:

    标签: java


    【解决方案1】:

    使用String s= new String("how many object b created by this method "); 创建一个String类的新对象's',你将字符串“这个方法创建了多少个对象b”传递给它的构造函数。

    String s1="Is this method is good as compare to upper"; 's1' 是一个字符串文字。关于字符串文字:

    每次您的代码 创建一个字符串文字,JVM 首先检查字符串文字池。 如果字符串已经存在于 池,对池的引用 实例返回。如果字符串确实 池中不存在,一个新的字符串 对象实例化,然后放置在 游泳池。 Java可以做到这一点 优化,因为字符串是 不可变的,可以在没有的情况下共享 担心数据损坏。

    source

    以上概念与string interning有关;所有文字字符串和字符串值常量表达式都在 Java [source] 中实习。所以基本上,只有当"Is this method is good as compare to upper" 不在池中时,使用String s1="Is this method is good as compare to upper"; 才会创建一个新对象。

    【讨论】:

    • String s1 = new String("hello"); ,在 JVM 级别创建了多少引用?我知道两个对象:1 在为“hello”加载类时,1 在实际执行命令时。 1 引用是 s1,我怀疑还有第二个引用 s2,它是在类加载时传递给“new String()”构造函数的“hello”字符串的结果。在java中,我们无法在函数或构造函数中传递对象本身,我们只能传递引用。另外,应该有第三个引用 s3,它应该是 new String("hello") 的结果,然后被分配给 s1?
    【解决方案2】:

    使用String s1="some string" 不会创建新的字符串对象。每个 String 字面量都已经存在 String 对象。

    具有相同值的字符串字面量用单个字符串对象表示,因此如果您同时使用String s1="some string"; String s2="some string";,则s1s2 指的是相同的"some string" 对象。

    new String("...") 创建一个新的 String 对象,它使用与 String 对象相同的数据来传递给构造函数的值“...”。

    【讨论】:

      【解决方案3】:

      考虑:

      String s1 = new String("hi");
      String s2 = new String("hi");
      System.out.println(s1 == s2);
      

      将打印false

      然而

      String s1 = "hi";
      String s2 = "h1";
      System.out.println(s1 == s2);
      

      将打印true

      还有

      String s1 = "hi";
      String s2 = new String("hi");
      System.out.println(s1 == s2);
      

      将打印false

      这就是为什么在比较Strings 时应该始终使用String.equals 而不是==

      但不要相信我的话...查看Java语言规范JLS 3.10的这段摘录:

      Thus, the test program consisting of the compilation unit (§7.3):
      
          package testPackage;
          class Test {
                  public static void main(String[] args) {
                          String hello = "Hello", lo = "lo";
                          System.out.print((hello == "Hello") + " ");
                          System.out.print((Other.hello == hello) + " ");
                          System.out.print((other.Other.hello == hello) + " ");
                          System.out.print((hello == ("Hel"+"lo")) + " ");
                          System.out.print((hello == ("Hel"+lo)) + " ");
                          System.out.println(hello == ("Hel"+lo).intern());
                  }
          }
          class Other { static String hello = "Hello"; }
      
      and the compilation unit:
      
          package other;
          public class Other { static String hello = "Hello"; }
      
      produces the output:
      
          true true true true false true
      
      This example illustrates six points:
      
          Literal strings within the same class (§8) in the same package (§7) represent references to the same String object (§4.3.1).
          Literal strings within different classes in the same package represent references to the same String object.
          Literal strings within different classes in different packages likewise represent references to the same String object.
          Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
          Strings computed by concatenation at run time are newly created and therefore distinct. 
      
      The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents. 
      

      【讨论】:

      • 两个注意事项:我很好奇“错误”案例 #5 在最新版本的 java 中是否发生了变化(新的优化?),但今天运行它是完全一样的,spec也是一样的。此外,如果它对其他人有所帮助,我发现 other.Other 令人困惑,直到我意识到小写的 other 是一层深的包名称,而不是缺少的变量或字段。
      【解决方案4】:

      在Java中创建String对象有两种方式:

      • 使用 new 运算符。例如,

        String str = new String("Hello");

      • 使用字符串文字或常量表达式)。例如,

        字符串 str="你好"; (字符串文字)或
        字符串 str="Hel" + "lo"; (字符串常量表达式)。

      字符串文字池:

      字符串分配,和所有对象一样 分配,在这两个时间都被证明是昂贵的 和记忆。 JVM 执行一些 实例化字符串时的诡计 文字以提高性能和 减少内存开销。削减 创建的 String 对象的数量 在 JVM 中,String 类保持一个 字符串池。每次你的代码 创建一个字符串文字,JVM 首先检查字符串文字池。 如果字符串已经存在于 池,对池的引用 实例返回。如果字符串确实 池中不存在,一个新的字符串 对象实例化,然后放置在 游泳池。

      【讨论】:

        【解决方案5】:

        使用 NEW 关键字创建 String 对象总是会在堆中创建一个包含所需字符串的对象,并返回堆中创建的对象的引用。

        创建没有 NEW 关键字的 String 对象(使用文字)首先检查字符串文字池中具有相同数据的现有字符串,如果找到,则返回来自字符串文字池的相同引用,否则,一个新的在字符串字面量池中创建并返回其引用。

        【讨论】:

          猜你喜欢
          • 2021-06-26
          • 1970-01-01
          • 1970-01-01
          • 2014-11-26
          • 1970-01-01
          • 2014-08-01
          • 1970-01-01
          • 2012-04-20
          • 1970-01-01
          相关资源
          最近更新 更多