JavaSE基础知识(十八)--Java多态之继承与清理中共享对象的清理

Java SE 是什么,包括哪些内容(十八)?

本文内容参考自Java8标准
再次感谢Java编程思想对本文的启发!
这个知识点是紧接着上篇博文中谈到的清理问题的一个特例进行说明,虽然在Java中需要主动清理对象的情况在极少数,但是还是需要了解一下。
在上篇博文中的示例代码中,每个类对象的组合对象都是这个类单独拥有的,和其他的类并没有产生任何关系(有兴趣可以参看上篇博文中的示例代码,每个类中的组合对象都进行了初始化,都是单独拥有的,不存在与其他类对象共享的情况)。
Java多态之继承与清理 https://blog.csdn.net/ruidianbaihuo/article/details/99704470.
那么,接下来我们需要讨论一下:如果一个对象被多个其它的对象共享了,那么清理这个对象的时机在什么时候最合适?
答案是:这个对象需要在其他对象都被清理完毕之后再清理。
代码示例:

// 共享对象的清理时机
   //类Shared,代表的是共享对象。
   class Shared{
      //int类型的类变量refcount,初始化值为0
      //它的作用是计数这个Shared对象被共享了几次。
      private int refcount = 0;
      //int类型的类变量counter,初始化值为0
      //static修饰,仅一份,与对象无关,与类有关,用于计数
      //共创建了多少个当前类的对象
      private static long counter = 0;
      //int类型的类变量id,用于标识当前对象的号码
      //final修饰表示一但初始化,不能被改变
      private final long id = counter++;
      //构造方法
      public Shared(){
         //打印字符串"Creating" + this
         //打印this,实际上调用的是方法toString()
         System.out.println("Creating" + this);
      }
      //方法addRef()
      public void addRef(){
         //将类变量refcount的值在原有基础上自增1
         refcount++;
      }
      //清理方法dispose()
      protected void dispose(){
         //如果--refcount的值等于0,则执行清理
         //这里为什么是--refcount而不是refcount--
         //因为判断条件是需要--refcount这个表达式的值为0
         //(而不是refcount的值为0,是整个表达式的值,--refcount这个表达式
         //在表示自减的同时还能表示一个值).
         //表示已经没有Composing对象了,已经清除完毕了。
         //可以清理那个共享的Shared对象了。
         if(--refcount == 0){
            //打印字符串"Disposing" + this
            //打印this,实际上调用的是方法toString()
            System.out.println("Disposing" + this);
         }
      }
      //方法toString()
      public String toString(){
         //返回字符串"Composing" + id
         return "Shared" + id;
      }
   }
   //类Composing
   class Composing{
      //组合类Shared。尚未初始化。
      private Shared shared;
      //long类型的类变量counter,用于计数。初始化值为0
      private static long counter = 0;
      //long类型的类变量id,用于标识当前创建的Composing对象是第几个。
      //新创建的对象是在原数值基础上+1,所以是counter++,而不是++counter
      //一但赋值,不能被改变,所以是final修饰。
      private final long id = counter++;
      //构造方法,带一个Shared类型的形式参数
      Composing(Shared shared){
         //打印字符串"Creating" + this
         //打印this,实际上调用的是方法toString()
         System.out.println("Creating" + this);
         //将类变量shared初始化。
         this.shared = shared;
         //调用初始化当前类变量shared的那个对象的addRef()方法。
         //因为refcount的作用是计数对象Shared被共享了几次,创建一个
         //类Composing对象就代表被共享了一次,所以refcount就要+1
         //所以直接在类Composing的构造方法里调用方法addRef(),让创建
         //类Composing对象的时候,变量refcount的值自动+1
         this.shared.addRef();
      }
      //清理方法dispose()
      protected void dispose(){
         //打印字符串"Creating" + this
         //打印this,实际上调用的是方法toString()
         System.out.println("Disposing" + this);
         //共享对象shared的清理
         shared.dispose();
      }
      //方法toString()
      public String toString(){
         //返回字符串"Composing" + id
         return "Composing" + id;
      }
   }
   //类ReferenceCounting
   public class ReferenceCounting{
      //程序执行入口main方法
      public static void main(String[] args) {
         //创建共享的对象Shared,
         //你需要注意的,什么说是共享,因为它只有一个。
         Shared shared = new Shared();
         //创建类Composing数组composing
         //一共包含了五个Composing对象。
         //它们共享了一个Shared对象。
         Composing[] composing = {
            new Composing(shared),new Composing(shared),
            new Composing(shared),new Composing(shared),
            new Composing(shared)
         };
         //for循环遍历类Composing数组composing
         for(Composing c:composing){
            //执行清理,实际上对象shared的清理动作只有在数组composing
            //中最后一个对象被清理完毕后才会发生
            //如果不是这样,shared对象被提前清理了,那么其他依赖它的
            //composing对象就无法正常执行了。
            c.dispose();
         }
      }
   }

结果示例:
创建和销毁的示意。
static long counter跟踪所创建的Shared的示例的数量,还可以为id提供数值,counter的类型是long而不是int,这样可以防止溢出(这只是一个良好的代码实践),id是final的,因为我们不希望它的值再对象的生命周期中被改变。
在将一个共享对象附着到类上时,必须记住调用方法addRef()(我提过了,主要是计数Shared被共享了多少次),但是dispose()方法将跟踪引用计数,并决定何时执行清理,使用这种技巧需要加倍的小心。
PS:时间有限,有关Java SE的内容会持续更新!今天就先写这么多,如果有疑问或者有兴趣,可以加QQ:2649160693,并注明CSDN,我会就博文中有疑义的问题做出解答。同时希望博文中不正确的地方各位加以指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值