java和内存管理中的对象生命周期?

时间:2013-08-07 07:11:42

标签: java string object heap-memory

对于程序中的以下语句,将在堆内存和字符串常量池中创建多少个对象?

我需要明确对象创建。我读过的许多资料都没有详细说明。当对象被破坏时我很困惑。

String a="MAM"+"BCD"+"EFG"+"GFE";

将创建多少个对象?

我正在寻找有关对象,方法和类的生命周期的良好材料,以及JVM在动态更改和修改时如何处理它们。

6 个答案:

答案 0 :(得分:20)

"MAM"+"BCD"+"EFG"+"GFE"是一个编译时常量表达式,它编译成"MAMBCDEFGGFE"字符串文字。在加载包含上述代码的类时,JVM将从此文本中创建String的实例,并将此String放入字符串池中。因此String a = "MAM"+"BCD"+"EFG"+"GFE";不会创建任何对象,请参阅JLS 15.18.1. String Concatenation Operator +

除非表达式是编译时常量表达式(第15.28节),否则新创建String对象(第12.5节)。

它只是将池中String对象的引用分配给局部变量a

答案 1 :(得分:6)

只创建了一个对象。

string s1 = "java";
string s2 = "ja" + "va";
s.o.p(s1==s2);

该陈述产生真实。

String s1="java";
string s2 = "ja";
String s3 = s2 +"va";
s.o.p(s1==s3);

该陈述产生错误。

因此,最小的一个明显应该是永久的,然后'+'运算符生成新的字符串对象(在非常量池中使用new())。 所以,你提出的问题并不是永久性的。这意味着它只创建一个对象。

答案 2 :(得分:3)

只创建一个对象并将其放置在常量池中,除非它已经存在,在这种情况下使用现有对象。编译器将字符串常量连接在一起,如JLS 3.10.5和15.28中所述。

  

长字符串文字总是可以分解成更短的部分,并使用字符串连接运算符+

写成(可能带括号的)表达式

http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

答案 3 :(得分:3)

大多数答案似乎都集中在a)完整的表达式是一个编译时常量而b)该行本身不构造一个新对象而只是一个一个的引用 object。

但是到目前为止还没有提到过,String本身包含对内部char[]的引用(也在常量池中)。

摘要:常量池中有两个对象(Stringchar[])。该行既不会创建也不会破坏任何对象。

关于:

  

当对象被破坏时我很困惑。

没有对象被销毁,因为只有在卸载类本身时才会销毁常量池中的内容。最多可以说,参考a最终会超出范围。

答案 4 :(得分:2)

由于String a将编译为"MAMBCDEFGGFE",因此只会创建一个对象。

答案 5 :(得分:0)

在示例中声明单个堆对象的答案是正确的。但是,请考虑以下代码:

public class Tester
{
   public String a="MAM";
   public String b ="BCD";
   public String c = "EFG";
   public String d ="GFE";

   public Tester()
   {
      String abcd = a + b + c + d;
   }
}

在此示例中,创建了7个字符串。 a,b,c和d不会编译成单个常量 - 它们是成员。然后为每个+运算符创建1个字符串 - 从语义上讲,+是串联,但逻辑上它在内存中创建一个新字符串。前两个操作符字符串会立即被丢弃,现在可以进行垃圾回收,但仍会发生内存流失。

技术上有第8个对象。测试者的实例。

编辑:在评论中证明这是无稽之谈