【Thinking in Java】初始化与清理(一)

来源:互联网 发布:淘宝卖品牌要授权吗 编辑:程序博客网 时间:2024/05/19 16:36

方法重载

方法名相同,方法参数列表不同(参数个数、类型、顺序),称之为重载。

参数顺序不同虽然也能区分两个方法,但是会使得代码难以理解,不建议使用。

方法的返回值是不能区分方法的。对于一个返回int的func()和一个返回void的func(),你都能在代码里直接调用func()而不赋值给另一个变量,所以不能通过返回值重载。


默认构造器

每个类都有一个默认构造器,但是当你定义了一个新的、有参数的构造器时,默认构造器自动失效了,除非你再手动定义一个默认构造器。


在构造器中调用构造器

public class Flower {int num;String name;public Flower(int i){this.num=i;}public Flower(String str){this.name=str;}public Flower(int i,String str){//System.out.println("Can't print here");this(i);this.name=str;}public Flower(String str,int i){this(str);this.num=i;}}

this(i);即在构造器中调用了另一个构造器。注意这种调用只能置于最起始处,不然会报错。


垃圾回收器

Java中的垃圾回收器只负责回收new出来的对象所占的内存。对于其他并非使用new所获得的内存空间,垃圾回收器无法处理,必须借用finalize()方法。

垃圾回收器需要消耗额外的系统资源,所以除非人为的调用和系统内存不足,垃圾回收器一般不主动工作。

在垃圾回收器准备好释放对象占用的内存空间时,会先调用finalize()方法。因此,我们能通过重写finalize()方法实现一些事情。


垃圾回收机制

引用计数只是用来说明垃圾回收的工作方式。每个对象都有一个引用计数器,用来记录对象的引用总数。当某个对象的引用计数为0,即没有任何引用时,垃圾回收器就能够释放这个对象所占的内存了。

但是如果对象之间出现循环引用,单纯的引用计数方式是无法回收这些对象所占的内存的。

JVM采用了一种自适应的垃圾回收技术:停止-复制 + 标记-清扫。

引用计数是查看一个对象有多少引用,而上述两种方法是查看一个引用指向了哪一个对象。

停止-复制方法:先暂停程序,将存活的对象从一个堆复制到另一个堆,没有复制的就是垃圾。(如何知道对象存活?书上没有细说,但我认为应该不是用引用计数的方法,而是跟标记-清扫一样,从引用出发,找到一个对象就复制,最后剩下的就是垃圾)。

标记-清扫方法:从引用出发,找到一个对象就对其进行标记。在遍历完所有引用之后,没有被标记的对象就是垃圾。

停止-复制方法能得到一块连续的内存,但是需要2倍的空间,适用于产生大量垃圾的情况。标记-清扫不需要额外的空间,但得到的是离散的内存,在只有少量垃圾的情况下,速度较快。

JVM使用上述两种方法的结合,以提高垃圾回收的效率。


finalize()方法

finalize()方法极少用到。只考虑一种特殊情况:在Java中调用非Java代码(如C++中的malloc()函数),分配了一块垃圾回收器回收不了的内存空间,这时候才需要重写finalize()方法,调用free()函数释放。

另外,finalize()方法可以用来提示我们哪个对象忘了进行某种必要操作。如以下代码,我们规定一个好的设计规范是Book对象必须进行标记,我们可以通过finalize()方法来检查是否所有Book对象都进行了标记。

public class TerminationCondition {public static void main(String args[]){Book book=new Book();book.mark();new Book();System.gc();}}class Book{boolean bool;public Book(){this.bool=false;}public void mark(){this.bool=true;}protected void finalize(){if(!bool){System.out.println("Not marked!");}}}


0 0
原创粉丝点击