zoukankan      html  css  js  c++  java
  • static、final和finalize详解

    一、static 修饰符

    1. 数据共享

      1. 成员变量(实例变量)和静态变量(类变量)的区别
        1. 两个变量的生命周期不同
          成员变量随对象的创建而存在,随对象被回收而释放
          静态变量随类的加载而存在,随类的消失而消失
        2. 调用方式不同
          成员变量只能被对象调用
          静态变量还可以被类名调用
        3. 数据存储位置不同
          成员变量–>堆内存的对象中,也叫对象的特有数据
          静态变量–>方法区(共享数据区)的静态区,也叫对象的共享数据
    2. 修饰变量: 每个对象都共有的属性就可以设置为static,被修饰的成员被所有的对象共享,且可以直接用  类名.X静态成员  的方式调用
                         static优先于对象存在,因为static成员随类的加载就已经存在了

    3. 修饰方法:静态方法 静态方法只能访问静态成员(非静态既可以访问静态也可以访问非静态) 静态方法中不可以使用this或者super关键字(对象不存在)

    4. 修饰代码块:静态代码块 随着类的加载而运行,而且只运行一次
                           作用:用于类的初始化

    5. 修饰类 : static不可以修饰普通类,可以修饰内部类

    二、final 修饰符

          1、修饰变量:  修饰基本数据类型变量,值不可以改变,表示常量;

                                    对final修饰的类属性和对象属性而言,如果不显示初始化,其默认将是进行默认初始化后的值,这与final本身出发点矛盾,
                                    因此,Java语法规定:

                                    final修饰的类属性和变量属性必须要进行显示初始化赋值。


                                    修饰应用数据类型变量,对象的应用不可以变,对象的属性可以改变。

           2、修饰方法: 方法不可被重写

           3、修饰类: 类不可被继承

           final修饰符的作用:起到安全作用。

    三、finalize

         1、finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。

          2、Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行

          3、finalize方法可能会带来性能问题。因为JVM通常在单独的低优先级线程中完成finalize的执行

          4、对象再生问题:finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的

                 例子:对象复活

     1 public class Test {
     2     private static Test TEST= null;
     3     public static void main(String args[]) {
     4         TEST = new Test();
     5         
     6         TEST = null;
     7         System.gc();
     8         try {
     9             Thread.sleep(500);
    10         } catch (InterruptedException e) {
    11             e.printStackTrace();
    12         }
    13         System.out.println(TEST);
    14         
    15         TEST = null;
    16         System.gc();
    17         try {
    18             Thread.sleep(500);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         System.out.println(TEST);
    23     }
    24     
    25     @Override
    26     public void finalize() throws Throwable {
    27         System.out.println("要死了要死了要死了!");
    28         TEST = this;
    29     } 
    30 }

    执行结果如下:

    1 要死了要死了要死了!
    2 com.Test@1aa9f99
    3 null

    可以看到在第一次垃圾回收时,在finalize方法给当前回收对象赋值给了新的引用,避免了被回收,不过finalize方法一个对象只能调用一次,在第二次回收时将不会被调用了。

    从上述两个例子中我们可以得出:finalize可以监听一个对象被回收,但是不能保证调用了finalize的对象一定会被回收,同时一个对象在第二次标记回收时是不会触发finalize的!如果想绝对监听一个对象是否被回收,只有在JVM里面添加参数-XX:+PrintGCDetails分析GC日志咯

     

           5、finalize方法至多由GC执行一次(用户当然可以手动调用对象的finalize方法,但并不影响GC对finalize的行为)

  • 相关阅读:
    Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception
    Microsoft Enterprise Library 5.0 系列(九) Policy Injection Application Block
    Microsoft Enterprise Library 5.0 系列(三) Validation Application Block (高级)
    软件研发打油诗祝大家节日快乐
    从挖井的故事中想到开发管理中最容易忽视的几个简单道理
    ITIL管理思想的执行工具发布
    管理类软件设计“渔”之演化
    20070926日下午工作流与ITILQQ群 事件管理 讨论聊天记录
  • 原文地址:https://www.cnblogs.com/javalyy/p/8880702.html
Copyright © 2011-2022 走看看