我在看java编程思想有个地方不太明白代码如下:
public class Book {
boolean checkedOut = false;
public Book(boolean checkedOut) {
this.checkedOut = checkedOut;
} public void checkedIn() {
checkedOut = false;
} public void finalize() {
if (checkedOut) {
System.out.println("ERROR: checked out");
}
} public static void main(String[] args) {
Book b = new Book(true);
new Book(true);
System.gc();
}
}执行后显示:
ERROR: checked out
因为new Book(true);(不是Book b = new Book(true);而是下面这行)被回收,调用了finalize函数而显示的如果我改成:
public static void main(String[] args) {
Book b = new Book(true);
b = null;
System.gc();
}
同样的道理,b=null而垃圾回收器要回收Book b = new Book(true);这行生成的对象但是我改成:
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
System.gc();
}
却不显示了,就是说没有回收,按道理来说b在if以内才有效,除了if的大括号应该就是垃圾了亚。在调用System.gc();的时候,也应该回收Book b = new Book(true);这样所产生的对象呀?但是为什么没有?
public class Book {
boolean checkedOut = false;
public Book(boolean checkedOut) {
this.checkedOut = checkedOut;
} public void checkedIn() {
checkedOut = false;
} public void finalize() {
if (checkedOut) {
System.out.println("ERROR: checked out");
}
} public static void main(String[] args) {
Book b = new Book(true);
new Book(true);
System.gc();
}
}执行后显示:
ERROR: checked out
因为new Book(true);(不是Book b = new Book(true);而是下面这行)被回收,调用了finalize函数而显示的如果我改成:
public static void main(String[] args) {
Book b = new Book(true);
b = null;
System.gc();
}
同样的道理,b=null而垃圾回收器要回收Book b = new Book(true);这行生成的对象但是我改成:
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
System.gc();
}
却不显示了,就是说没有回收,按道理来说b在if以内才有效,除了if的大括号应该就是垃圾了亚。在调用System.gc();的时候,也应该回收Book b = new Book(true);这样所产生的对象呀?但是为什么没有?
如果我改成:
public static void main(String[] args) {
if(true) {
Book b = new Book(true);
}
Book c = new Book(true);
c = null;
System.gc();
}
}
则显示:
ERROR: checked out
ERROR: checked out就是说回收了Book b = new Book(true);和Book c = new Book(true);产生的对象如果我这样:
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
new Book(true);
System.gc();
}
}
则显示:
ERROR: checked out,就是说只回收了new Book(true);产生的对象
按照你说的:当你的对象不存在任何引用的时候,gc才会回收垃圾对象。为什么第一个对b进行了回收,说明b不存在应用了(可以看成b=null吧?),但是第二个例子为什么不对b进行回收呢?
new Book(true);这两句代码中。垃圾回收器system.gc()是在一块内存没被引用的这种条件下做回收的。从上面两句代码看出"b"指针指向new Book(true)这块地址,说明new Book(true)在被引用中。后面句“new Book(true)”没有被任何指针引用,那么它就属于一块垃圾,垃圾车(system.gc)来后,一下子就被清理了。
Book b = new Book(true);
}但是这样的b.在{}外面就是没有用的了,但是b的指针还是指向new Book(true);这块地址,虽然程序不用了,但是jvm没有给它看做垃圾,还是什么?总之它没有回收亚
public static void main(String[] args) {
for(int i=1;i<2;i++)
{
Book b = new Book(true);
}
System.gc();
}
针对LZ的发言,if (true) {
Book b = new Book(true);
}
b指针是已经存在的,虽然b在程序中没有使用,但b指定的地址new Book(true)也不是垃圾,因为b指向new Book(true),它们的关系没有断开.就像有美女拎着一塑料袋,她仍到垃圾箱时,这时美女跟塑料袋脱离了关系,袋子没有了价值,现在袋子就是垃圾,当她把袋子作为装零食的容口或者放在衣袋里,那么袋子跟美女还存在的关系。
所以在这里b没有把new Book(true)甩掉,所以垃圾车不用去扫垃圾。现在针对"lgh2008(ar_guang)"的发言进行解析!
public static void main(String[] args) {
for(int i=1;i<2;i++)
{
Book b = new Book(true);
}
System.gc();
}
一看这段代码就会产生垃圾,在这个循环中Book b实例变量的作用范围只存在于这个循环体内,每次循环,都要建立一个new Book(true)对象,它都在循环结束时,这个实例变量将在堆栈移除,这时实例变量对应的内存地址没有指针引用,所以成一块垃圾内存,如果改为for(int i=1;i<6;i++),那么将产生6块垃圾地址。LZ: public static void main(String[] args) {
Book b = new Book(true);
b = null;
System.gc();
}
同样的道理,b=null而垃圾回收器要回收Book b = new Book(true);这行生成的对象
-------------------------------
这里也是一样的道理,首先创建了Book对象,b指向new Book(true)地址,后面句b = null的意思是b断开了与任何对象的联系。所以前面建立的对象new Book(true)将被孤独,成为垃圾内存地址,如果new Book(true)没有被释放,那么破坏者可以通过这块内存进行攻击。
谢谢你,我懂了
但是这样写得话
if (true) {
Book b = new Book(true);
}
虽然在程序中b看成了垃圾,但是在jvm中没有看成垃圾,如果像这样的情况在程序中的很多的话,是不是他们都不能被释放。对吗?如果是,那么一般来说,最好是这样写:
if (true) {
Book b = new Book(true);
b= null;
}
对吗?这样的话。在gc的时候就可以释放内存了,不知道我这样理解对不?
我有个问题还是没太搞清楚,请解释下:
class Book
{
boolean checkedout = false ;
Book(boolean checkedout)
{
this.checkedout=checkedout;
}
void checkin()
{
checkedout=false;
}
public void finalize()
{
if(checkedout)
{
System.out.println("Error: checkedout");
}
}
}
public class finalize
{
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
Book c = new Book(true);
c = null;
System.gc();
}}
怎么打印结果是两个:Error: checkedout呢
不是说b和那个对象还有联系吗
1、Book b = new Book(true)是建立在if代码体内的,那么它的作用范围只存在于if的范围内,也就是说在if范围外是不能调用b实例变量的。当if结束后实例变量b已经在堆栈被移除,那么new Book(true)内存地址就被孤立起来,成为垃圾。
2、Book c = new Book(true);
c = null;
这句代码我上面也说过的"首先创建了Book对象,c指向new Book(true)地址,后面句c = null的意思是c断开了与任何对象的联系。所以前面建立的对象new Book(true)将被孤独,成为垃圾内存地址,如果new Book(true)没有被释放,那么破坏者可以通过这块内存进行攻击。"
我看到你的回答又糊涂了:
你说的:
Book b = new Book(true)是建立在if代码体内的,那么它的作用范围只存在于if的范围内,也就是说在if范围外是不能调用b实例变量的。当if结束后实例变量b已经在堆栈被移除,那么new Book(true)内存地址就被孤立起来,成为垃圾。
但是这样:
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
System.gc();
}
按照你的解释:当if结束后实例变量b已经在堆栈被移除,那么new Book(true)内存地址就被孤立起来,成为垃圾。
但是这样怎么没有回收呢?
如果我是这样
public static void main(String[] args) {
if(true) {
Book b = new Book(true);
}
Book c = new Book(true);
c = null;
System.gc();
}
}
显示了两个:Error: checkedout 说明垃圾回收器动作了的,但是如果我这样
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
}
System.gc();
}
按照lllllllllluoyi(罗毅) 说的new Book(true);产生的对象也是垃圾。为什么回收器没有动作呢?如果说是回收器在内存不够的时候动作,为什么第一个就回收了呢?
这里我还是没有懂。
如果说:System.gc()只不是把对象置一个回收标志,表示它优先会被回收,并不等于实时回收,至于它什么时候回收就要看JVM的内部机制了。那为什么第一种情况就可以及时被回收,但是第二种情况却不能呢?
请详细看书,书上有很详细地说明
if(true) {
Book b = new Book(true);
}
Book c = new Book(true); //在这个地方jvm会检查有没有垃圾
c = null; //再次检查
System.gc();
}
}
显示了两个:Error: checkedout 说明垃圾回收器动作了的,但是如果我这样
public static void main(String[] args) {
if (true) {
Book b = new Book(true);
} //虽然b的作用于在if里,但是由于后面没有创建新的对象,所以jvm就不检查了。
System.gc(); //可以看出垃圾回收机制完全是被动性的,你new第二次该对象的时候她才
//会检查你上一个引用是否还有用。
}推理可得:下面这段代码将只打印一个 ERROR:...
public static void main(String[] args) {
if(true) {
Book b = new Book(true);
}
Book c = new Book(true);
System.gc();
}
}
for(int i = 0; i < 1; i++) {
Book b = new Book(true);
}
System.gc();
}
这个离开scope也是只生成一个对象啊,
却要打印出来
奇怪这又如何解释呢