6

我正在讨论Java中Strings 和s 的用法。StringBuffer这两个示例中的每一个都创建了多少个对象?

例 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

4 回答 4

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。

PS 为了使比较公平,您可能应该sb.toString()在第二个示例结束时调用。

于 2012-05-04T15:16:46.100 回答
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

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

于 2012-05-04T06:29:32.507 回答
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  
}
于 2012-05-04T06:51:17.197 回答
-1

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

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

For Ex2, the minimum number of objects is 2. The compiler has no way of knowing if we have replaced StringBuilder with a custom version with different semantics, so it will not optimize. The maximum could be around 6, for an extremely memory-conserving StringBuilder implementation that expands a backing char[] array one character at a time, but in most cases it will be 2 too.

于 2013-08-19T02:33:42.130 回答