• 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的行为)

  • 相关阅读:
    关于springMVC转换json出现的异常
    jQuery实现,动态自动定位弹窗。JS分页,Ajax请求
    servlet为什么要配置web.xml
    Jmeter系列(4)- Jmeter 脚本录制
    后缀数组模板
    NOIP2016 玩脱记
    TERSUS无代码开发(笔记21)-流程执行顺序思考(转载)
    ===>===>===>特色思TERSUS常用功能整理
    TERSUS无代码开发(笔记20)-本地开发测试mysql数据库连接
    TERSUS无代码开发(笔记19)-mysql-connector-java-5.-bin.jar下载方法
  • 原文地址:https://www.cnblogs.com/javalyy/p/8880702.html
Copyright © 2020-2023  润新知