创建了多少个对象

时间:2012-05-04 06:06:28

标签: java string object bytecode stringbuilder

我正在讨论在Java中使用StringStringBuffer的问题。在这两个例子的每一个中创建了多少个对象?

Ex 1:

String s = "a";
s = s + "b";
s = s + "c";        

前2:

StringBuilder sb = new StringBuilder("a");
sb.append("b");
sb.append("c");

在我看来,Ex 1将创建5,而Ex 2将创建4个对象。

4 个答案:

答案 0 :(得分:6)

我使用了内存分析器来获取确切的数量。

在我的机器上,第一个示例创建了8个对象:

String s = "a";
s = s + "b";
s = s + "c";
  • 两个类型为String的对象;
  • 两个类型为StringBuilder的对象;
  • 类型为char[]的四个对象。

另一方面,第二个例子:

StringBuffer sb = new StringBuffer("a");
sb.append("b");
sb.append("c");

创建2个对象:

  • 类型为StringBuilder的一个对象;
  • char[]类型的一个对象。

这是使用JDK 1.6u30。

P.S。为了使比较公平,您可能应该在第二个示例的末尾调用sb.toString()

答案 1 :(得分:5)

就创建的对象而言:

示例1创建了8个对象:

String s = "a"; // No object created
s = s + "b"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String)
s = s + "c"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String)

示例2创建了2个对象:

StringBuffer sb = new StringBuffer("a"); // 1 StringBuffer + 1 char[] (in SB)
sb.append("b"); // 0
sb.append("c"); // 0

公平地说,我不知道新的char []实际上是用Java创建了一个Object(但我知道它们是创建的)。感谢aix指出了这一点。

答案 2 :(得分:4)

您可以通过分析java字节码来确定答案(使用javap -c)。示例1创建了两个StringBuilder对象(参见第4行)和两个String对象(参见第7行),而示例2创建了一个StringBuilder对象(参见第2行)。

请注意,您还必须考虑char[]个对象(因为数组是Java中的对象)。 StringStringBuilder个对象都是使用基础char[]实现的。因此,示例1创建八个对象,示例2创建两个对象。

示例1:

public static void main(java.lang.String[]);
  Code:
   0:   ldc             #2; //String a
   2:   astore_1
   3:   new             #3; //class java/lang/StringBuilder
   6:   dup
   7:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   10:  aload_1
   11:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   14:  ldc             #6; //String b
   16:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   19:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   22:  astore_1
   23:  new             #3; //class java/lang/StringBuilder
   26:  dup
   27:  invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   30:  aload_1
   31:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   34:  ldc             #8; //String c
   36:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   39:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   42:  astore_1
   43:  return   
}

示例2:

public static void main(java.lang.String[]);
  Code:
   0:   new             #2; //class java/lang/StringBuilder
   3:   dup
   4:   ldc             #3; //String a
   6:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   9:   astore_1
   10:  aload_1
   11:  ldc             #5; //String b
   13:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  pop
   17:  aload_1
   18:  ldc             #7; //String c
   20:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   23:  pop
   24:  return  
}

答案 3 :(得分:-1)

答案与语言的特定实现(编译器和运行时库)有关。甚至是否存在特定的优化选项。当然还有实现的版本(并且,隐含地,它符合的JLS)。所以,最好用最小值和最大值来说话。事实上,这个练习提供了更好的

对于Ex1,最小对象数为1(编译器意识到只涉及常量并仅生成String s= "abc" ;的代码)。最大可能是任何东西,取决于实现,但合理的估计是8(在另一个答案中也给出了某些配置产生的数字)。

对于Ex2,最小对象数为2.编译器无法知道我们是否已将StringBuilder替换为具有不同语义的自定义版本,因此不会进行优化。对于一个极其节省内存的StringBuilder实现,最大值可以是6左右,它一次扩展一个后备char[]数组,但在大多数情况下它也是2。