学习随笔

C,Java,Python,Html代码重复意味着有改进空间

Java中关于垃圾收集和抽象类

创建对象会占据内存,如果程序执行流程中已无法再使用某个对象,该对象就只是徒耗内存的垃圾。对于不再有用的对象,JVM有垃圾收集( Garbage Collection,GC)机制,收集到的垃圾对象所占据的内存空间,会被垃圾收集器释放。那么,哪些会被JVM认定为垃圾对象?简单地说,执行流程中,无法通过变量参考的对象,就是GC认定的垃圾对象
执行流程具体来说就是线程( Thread)如main()程序进入点开始之后的主线程也就是主流程。事实上,关于垃圾收集本身就很复杂,不同的需求也会有不同垃圾收集算法,只需要知道基本概念即可,细节就交给JVM处理。
假设有一个类:

public class Some{
    Some next;
}

若是从程序进入点开始,有段程序代码如下撰写:

Some some1=new Some();
Some some2=new Some();
Some some1=some2;

执行到第二行时,主线程可以通过参考名称所参考到的对象。执行到第三行时,是将some2参考的对象给some1参考。原先some1参考的对象不再被任何名称参考,通过主线程也不再能参考到该对象,这个对象就是内存中的垃圾了,GC会自动出这些垃圾并予以回收
GC的基本概念就是这样,但可以加以变化。如果有段程序是这样:

Some some =new Some();
some.next =new Some();
some=null;

此时还没有对象是垃圾。由于从主流程开始,可以通过some参考至中间的对象,而some.next可以参考至最后边的对象,目前没有必要回收任何对象。执行成第三行后。由于从主流程开始,无法通过some参考至中间对象,也就无法再通过中间对象的next参考至后边对象,所以两个对象都是垃圾。同样的道理,下面程序代码中,somes参考至null,数组参考到的对象全部都会被回收。

Some[] somes={new Some(),new Some(),new Some()};
somes=null

回收的对象包括了数组对象本身,以及三个索引所参考的三个对象。如果是形同孤岛的对象,例如

 Some some = new Some();
 some.next=new Some ();
 some.next.nextnew Some();
 some.next.next.next=some;
 some=null:

执行到第五行这个时候形成孤岛的三个对象,将全部被GC给处理掉。—->GC在进行回收对象前,会调用对象的 finalize()方法,这是 object上就定义的方法。如果在对象被回收前,有些事情想做,可以重新定义 finalize()方法,不过要注意的是何时启动GC,要视所采用的GC算法而定,也就是 finalize()被调用的时机是无法确定的。在 Effective Java书中也建议,避免使用 finalize()方法。
再看抽象类
撰写程序常有些看似不合理但又非得完成的需求。举个例子来说,现在开发一个猜数字游戏,会随机产生0-9的数字,用输入的数字与随机产生的数字相比,如果相同就显示“猜中了”,如果不同就继续让用户输入数字,直到猜中为止。

package hello;

import java.util.*;

public class GuessNum {
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        int num=(int) (Math.random()*10);
        int guess;
        do {
            System.out.println("输入数字:");
            guess=scan.nextInt();
        }while(guess==num);
        System.out.println("bingo");
    }
}

以上面的例子来说,取得用户输入、显示结果的环境未定,你就无法用上面的程序完成工作。在团队合作、多个部门开发程序时,有许多时候,你不能只是等另一个部门将程序操作出来,有些需求无法决定,却要撰写出程序。
有些不合理的需求,本身确实不合理,但看似不合理的需求,其实可以通过设计 Design()来解决。就像你负责的这部分还是可以先操作。例如:

public void go() {
        int num=(int) (Math.random()*10);
        int guess;
        do {
            System.out.println("输入数字:");
            guess=nextInt();
        }while(guess==num);
        println("bingo");
    }
    public void println(String text) {
        print(text+"\n");
    }
    public abstract int nextInt();
    public abstract void print(String text);

这个类的定义不完整, print()、 printn()与 nextint()都是抽象方法,因为还没决定在哪个环境执行猜数字游戏,所以如何显示输出、取得用户输入(System.out.println、Scanner scan=new Scanner(System.in);)就不能操作。可以先操作的是猜数字的流程,虽然是抽象方法,但在go()方法中,还是可以调用。如果终于还是在文本模式下执行猜数字游戏,你就再撰写 ConsoleGame类,继承抽象类 GuessGame,操作当中的抽象方法即可:

public class ConsoleGame extends GuessGame{
    private Scanner scan=new Scanner(System.in);
    @Override
    public void println(String text) {
        System.out.println(text);
    }

    @Override
    public void print(String text) {
        System.out.println(text);
    }

    @Override
    public int nextInt() {
        return scan.nextInt();
    }
}

之后只要创建ConsoleGame实例,执行go()方法就可以了

ConsoleGame game=new ConsoleGame();
game.go();
阅读更多
版权声明:博主原创或改进文章 https://blog.csdn.net/zkd758/article/details/79951822
文章标签: Java
个人分类: Java
上一篇java.lang.Object(数组收集对象&重新定义)
下一篇接口与多态
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭