zoukankan      html  css  js  c++  java
  • Java提高学习之Object(3)

    终止

    问: finalize()方法是用来做什么的?

    答: finalize()方法可以被子类对象所覆盖,然后作为一个终结者,当GC被调用的时候完成最后的清理工作(例如释放系统资源之类)。这就是终止。默认的finalize()方法什么也不做,当被调用时直接返回。

    对于任何一个对象,它的finalize()方法都不会被JVM执行两次。如果你想让一个对象能够被再次调用的话(例如,分配它的引用给一个静态变量),注意当这个对象已经被GC回收的时候,finalize()方法不会被调用第二次。

    问: 有人说要避免使用finalize()方法,这是真的吗?

    答: 通常来讲,你应该尽量避免使用finalize()。相对于其他JVM实现,终结器被调用的情况较少——可能是因为终结器线程的优先级别较低的原因。如果你依靠终结器来关闭文件或者其他系统资源,可能会将资源耗尽,当程序试图打开一个新的文件或者新的系统资源的时候可能会崩溃,就因为这个缓慢的终结器。

    问: 应该使用什么来替代终结器?

    答: 提供一个明确的用来销毁这个对象的方法(例如,java.io.FileInputStreamvoid close()方法),并且在代码中使用try - finally结构来调用这个方法,以确保无论有没有异常从try中抛出,都会销毁这个对象。参考下面释放锁的代码:

     1 Lock l = ...; // ... is a placeholder for the actual lock-acquisition code
     2 l.lock();
     3 try
     4 {
     5    // access the resource protected by this lock
     6 } 
     7 finally
     8 {
     9    l.unlock();
    10 }

    这段代码保证了无论try是正常结束还是抛出异常都会释放锁。

    问: 什么情况下适合使用终结器?

    答: 终结器可以作为一个安全保障,以防止声明的终结方法(像是java.io.FileOutputStream对象的close()方法或者java.util.concurrent.Lock对象的Lock()方法)没有被调用。万一这种情况出现,终结器可以在最后被调用,释放临街资源。

    问: 怎么写finalize()

    答: 可以遵循下面这个模式写finalize()方法:

     1 @Override
     2 protected void finalize() throws Throwable
     3 {
     4    try
     5    {
     6       // Finalize the subclass state.
     7       // ...
     8    }
     9    finally
    10    {
    11       super.finalize();
    12    }
    13 }

        子类终结器一般会通过调用父类的终结器来实现。当被调用时,先执行try模块,然后再在对应的finally中调用super.finalize();这就保证了无论try会不会抛出异常父类都会被销毁。

    问: 如果finalize()抛出异常会怎样?

    答: 当finalize()抛出异常的时候会被忽略。而且,对象的终结将在此停止,导致对象处在一种不确定的状态。如果另一个进程试图使用这个对象的话,将产生不确定的结果。通常抛出异常将会导致线程终止并产生一个提示信息,但是从finalize()中抛出异常就不会。

    问: 我想实践一下finalize()方法,能提供一个范例吗?

    答: 参考代码清单1.

     1 class LargeObject
     2 {
     3    byte[] memory = new byte[1024*1024*4];
     4  
     5    @Override
     6    protected void finalize() throws Exception
     7    {
     8       System.out.println("finalized");
     9    }
    10 }
    11  
    12 public class FinalizeDemo
    13 {
    14    public static void main(String[] args)
    15    {
    16       while (true)
    17          new LargeObject();
    18    }
    19 }

    代码清单1:实践finalize()

        代码清单1中的代码写了一个FinalizeDemo程序,重复地对largeObject类实例化。每一个Largeobject对象将产生4M的数组。在这种情况下,由于没有指向该对象的引用,所以LargeObject对象将被GC回收。

    GC会调用对象的finalize()方法来回收对象。LargeObject重载的finalize()方法被调用的时候会想标准输出流打印一条信息。它没有调用父类的finalize()方法,因为它的父类是Object,即父类的finalize()方法什么也不做。

    编译(javac FinalizeDemo.java)并运行(java FinalizeDemo)代码清单1.当我在我的环境下(64位win7平台)使用JDK7u6来编译运行的时候,我看到一列finalized的信息。但是在JDK8的环境下时,在几行finalized之后抛出了java.lang.OutOfMemoryError

    因为finalize()方法对于虚拟机来说不是轻量级的程序,所以不能保证你一定会在你的环境下观察到输出信息。

    得到对象的类

    问: gerClass()方法是用来做什么的?

    答: 通过gerClass()方法可以得到一个和这个类有关的java.lang.Class对象。返回的Class对象是一个被static synchronized方法封装的代表这个类的对象;例如,static sychronized void foo(){}。这也是指向反射API。因为调用gerClass()的对象的类是在内存中的,保证了类型安全。

    问: 还有其他方法得到Class对象吗?

    答: 获取Class对象的方法有两种。可以使用类字面常量,它的名字和类型相同,后缀位.class;例如,Account.class。另外一种就是调用ClassfoeName()方法。类字面常量更加简洁,并且编译器强制类型安全;如果找不到指定的类编译就不会通过。通过forname()可以动态地通过指定包名载入任意类型地引用。但是,不能保证类型安全,可能会导致Runtime异常。

  • 相关阅读:
    PHP链接xmpp,openfire新增用户,聊天室
    mysql数据库导入导出 授权
    docker容器的跨主机连接
    php编译安装
    WebIM web即时通信 基于openfire+smack的Android、Web、PC开发(一)
    某电商平台开发记要——客服系统
    架构
    kafka-python如何关闭debug日志
    【python编码】 UnicodeDecodeError 分析和解决
    I、Identical Day from 第二届“联想杯”
  • 原文地址:https://www.cnblogs.com/sunfie/p/5134254.html
Copyright © 2011-2022 走看看