在C ++中,您可以释放分配给对象的内存,如下所示:
int main(){
string myString("MyString");
string *stringPointer = &myString;
cout<<myString<<" "<<*stringPointer;
delete stringPointer;
cout<<myString; //crash
return 0;
}
在二叉搜索树(或任何其他情况)中,当您需要删除节点时,可以使其符合Java中的垃圾收集条件。但你不能这样做
Node nodeToDelete = getNodeToDelete();
nodeToDelete = null; //the original reference is still there in the tree
这就像在C ++中将指针变量设置为NULL
pointerVariable = NULL;
要使BST删除功能在Java中工作,我们需要转到节点的父节点并将子节点设置为删除为null。 是否有像C ++中的delete这样的Java语言功能,以使事情变得更容易?
答案 0 :(得分:1)
不,Java中没有语言功能允许您提前有选择地删除特定对象(如Python中的del
)。你需要相信垃圾收集器会完成它的工作。 (通常情况下,这样做非常好。)
Java的垃圾收集器基于对象可达性(不是像CPython中的引用计数,而不是像Boehm GC中那样的内存扫描)。这样,任何没有实时引用的对象都会被垃圾回收。参考可以是间接的,但死物和死循环的参考不会刺激车库收集器。
一些例子:
class Dummy {
String name;
Dummy other;
Dummy(String name) { this.name = name; }
}
void f1() {
Dummy peter = new Dummy("Peter");
peter.other = new Dummy("Fred");
peter.other.other = new Dummy("Megan");
// None of the objects is eligible for garbage collection since
// "Peter" is live and "Fred" can be reached via "Peter" (therefore
// "Fred" is alive) and "Megan" can be reached via "Fred".
peter.other = null;
// Now the reference to "Fred" is lost which makes him a candidate
// for garbage collection. "Megan" is dead too because the
// reference from the dead object "Fred" does not count.
// As the method returns, all three objects are dead and can be
// collected.
}
void f2() {
Dummy clementine = new Dummy("Clementine");
clementine.other = new Dummy("Charles");
clementine.other.other = new Dummy("Caroline");
clementine.other.other.other = clementine;
// Here we have a cycle of
//
// +--> "Clementine" --> "Charles" --> "Caroline" --+
// | |
// +------------------------------------------------+
//
// and since "Clementine" is live, all three are.
clementine = null;
// Once we loose the reference to "Clementine", the cycle still
// exists (every object is referenced by at least one other object)
// but the cycle is dead. Hence, all three are subject to garbage
// collection.
}
有效使用Java垃圾收集的关键是不要保留对不再需要的对象的任何引用。在二叉树中,执行
this.leftChild = null;
将使整个左子树符合垃圾回收的条件。 (也就是说,如果没有其他人保持对其中一个节点的实时引用。)
只有很少你想让垃圾收集器收集一个活动对象。这可以使用java.lang.ref.SoftReference
完成。我发现它们唯一有用的是缓存。
import java.lang.ref.SoftReference;
class StoryOfMyLife {
private final String story;
private transient SoftReference<String[]> cachedWords;
public StoryOfMyLife(final String story) {
this.story = story;
this.cachedWords = new SoftReference<String[]>(null);
}
public synchronized String getWordN(final int n) {
String[] words = this.cachedWords.get();
if (words == null) {
// Called for the first time or cache was garbage collected.
words = this.story.split("\\s+");
this.cachedWords = new SoftReference<String[]>(words);
}
// Note that we are keeping the cache live for the duration of
// this method by keeping the reference 'words'. Once this
// method returns, the cache becomes subject to garbage
// collection again.
return words[n];
}
}
在这个例子中,(可能非常昂贵的)将长字符串拆分为单词只是懒惰地完成并且结果被缓存。但是,如果系统内存不足,我们允许缓存被垃圾收集,因为我们可以随时重新计算它。
您可以在Oracle's website了解有关Oracle HotSpot JVM内置垃圾收集器的更多信息。
答案 1 :(得分:0)
Java使用基于可达性的垃圾收集来管理内存,因此为了释放内存,只需确保它不再可用。
很少有Java对象需要及时清理:
即管理本机资源的那些。使用dispose()
或if block-scoped, try using
。
旁注:C ++对使用错误方法释放内存过敏:
delete
来补充new
。delete []
来补充new[]
。free
来补充malloc
,calloc
和realloc
。