Java中的内存分配和管理

时间:2014-02-12 11:10:06

标签: java memory-management

有人请说明下面我要更好地掌握java内存分配和管理。感谢。

Q1)以下3个代码片段之间的差异是什么:为什么存在三种不同? (就内存分配而言)

片段1:

Class C
{

StringBuffer sb = new StringBuffer();

C(){}

}

Fragment2:

Class C
{

StringBuffer sb;

C()
{
sb = new StringBuffer();
}

}

Fragment3:

Class C
{

C()
{
StringBuffer sb = new StringBuffer();
}

}

Q2)如何在没有任何参考变量的情况下创建对象。 例如, new C(); new C()。Hello(); 如何理解他们的内存管理,默认值,范围!!

Q3)以下2个片段之间的差异

片段1

Class C
{
int a;
C(){}
}

Fragment2

Class C
{
C(){int a;}
}

3 个答案:

答案 0 :(得分:1)

Q1)片段1和片段2是等价的。如果类C有多个构造函数,则会有所不同。在片段1变体中,您只需编写一次初始化,在片段2变体中,您需要在每个构造函数中编写它。

在片段3中,变量sb是构造函数中的局部变量,只在那里可见。当构造函数结束时,StringBuffer对象可以被垃圾收集。

Q2)无法维护,创建后可立即进行垃圾回收。在new C().Hello();的情况下,只有在Hello()方法退出时才保证对象存在。

Q3)片段1声明一个类字段,片段2是构造函数中的局部变量。

答案 1 :(得分:1)

Fragment1Fragment2实际上是相同的。它们都具有相同的范围,并创建相同的对象。在后者中,这是在构造函数中完成的。这就是区别。在我看来,成员通常应该在构造函数中初始化。

Fragment3范围不同。一旦构造函数结束,C就会被垃圾收集。这是因为,当方法完成时,所有本地对象都被解除引用。一旦没有引用指向实例,垃圾收集器就会做它最擅长的事情。收集该死的垃圾。

存在三个不同的例子,因为......好吧......它们可以在几种不同的情况下使用。您可能有一个依赖于另一个成员的成员,因此只能在第一个成员之后初始化。

示例

public class Test
{
    private A a;
    private B b;

    public Test()
    {
        b = new B();
        // As you can see, b needs to exist first.
        a = new A(b);
    }
  

如何维护没有任何引用变量的对象。例如,new C(); new C()。Hello();如何理解他们的内存管理,默认值,范围!!

如果没有对象的引用,那么它将被垃圾收集。声明new A()时,只要您使用它就存在。第二个程序跨过那行代码(或字节代码的集合),垃圾收集器再次清理。

  

Q3)以下2个片段之间的差异:

在第一个示例中,a可以在类中的任何位置使用。这称为global variable,或者更具体地称为instance variable。在第二个示例中,您声明了一个local变量。这意味着它只能在声明它的方法中使用。在这种情况下,构造函数。

答案 2 :(得分:0)

其他答案的补充:

如果创建了一个新对象,JVM将始终在正在运行的程序的堆中分配内存并将该对象放在那里。在所有示例片段中,生成的StringBuffer对象将放在堆中。

使用new关键字创建新对象也会返回对该对象的引用。可以将此引用分配给变量。这里是你的示例片段的不同之处。在片段1和片段2中,您将此引用分配给实例变量(aka字段),该变量是对象数据的一部分 - 这里是类C的实例。因此,这些实例变量也驻留在堆中。只要还有对C实例的引用 - 可能在您的main方法中 - 肯定会引用包含的StringBuffer实例。

在片段3中,将此引用分配给局部变量。局部变量的内存分配在堆栈上,而不是堆上。当方法结束时,也将丢弃此内存分配。没有(本地)变量,可以保存对象的引用。

如果对象没有引用,则该对象被认为有资格进行垃圾回收。在您的片段3中,构造函数结束后StringBuffer实例将是这种情况。请注意,Java垃圾收集器不会立即运行并删除所有垃圾。它将在JVM选择的适当时间运行。