inheritance and cleanup

本文探讨了在使用继承和组合创建新类时如何处理资源清理问题,特别是在Java中。通过实例展示了如何正确覆盖dispose()方法来确保基类和子类的资源得到妥善释放,并介绍了引用计数在共享对象清理中的应用。

When using composition and inheritance to create a new class, most of the time you won’t worry about cleanup. Subobjects can usually be left to the garbage collector. If you do have cleanup issues, you must be diligent and create a dispose() method for you new class.

When you override dispose() in an inherited class, it’s important to remember to call the base-class version of dispose() , since otherwise the base-class cleanup will not happen.

for example:

// polymorphism/Frog.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Cleanup and inheritance
// {java polymorphism.Frog}
package polymorphism;

class Characteristic {
  private String s;

  Characteristic(String s) {
    this.s = s;
    System.out.println("Creating Characteristic " + s);
  }

  protected void dispose() {
    System.out.println("disposing Characteristic " + s);
  }
}

class Description {
  private String s;

  Description(String s) {
    this.s = s;
    System.out.println("Creating Description " + s);
  }

  protected void dispose() {
    System.out.println("disposing Description " + s);
  }
}

class LivingCreature {
  private Characteristic p = new Characteristic("is alive");
  private Description t = new Description("Basic Living Creature");

  LivingCreature() {
    System.out.println("LivingCreature()");
  }

  protected void dispose() {
    System.out.println("LivingCreature dispose");
    t.dispose();
    p.dispose();
  }
}

class Animal extends LivingCreature {
  private Characteristic p = new Characteristic("has heart");
  private Description t = new Description("Animal not Vegetable");

  Animal() {
    System.out.println("Animal()");
  }

  @Override
  protected void dispose() {
    System.out.println("Animal dispose");
    t.dispose();
    p.dispose();
    super.dispose();
  }
}

class Amphibian extends Animal {
  private Characteristic p = new Characteristic("can live in water");
  private Description t = new Description("Both water and land");

  Amphibian() {
    System.out.println("Amphibian()");
  }

  @Override
  protected void dispose() {
    System.out.println("Amphibian dispose");
    t.dispose();
    p.dispose();
    super.dispose();
  }
}

public class Frog extends Amphibian {
  private Characteristic p = new Characteristic("Croaks");
  private Description t = new Description("Eats Bugs");

  public Frog() {
    System.out.println("Frog()");
  }

  @Override
  protected void dispose() {
    System.out.println("Frog dispose");
    t.dispose();
    p.dispose();
    super.dispose();
  }

  public static void main(String[] args) {
    Frog frog = new Frog();
    System.out.println("Bye!");
    frog.dispose();
  }
}
/* Output:
Creating Characteristic is alive
Creating Description Basic Living Creature
LivingCreature()
Creating Characteristic has heart
Creating Description Animal not Vegetable
Animal()
Creating Characteristic can live in water
Creating Description Both water and land
Amphibian()
Creating Characteristic Croaks
Creating Description Eats Bugs
Frog()
Bye!
Frog dispose
disposing Description Eats Bugs
disposing Characteristic Croaks
Amphibian dispose
disposing Description Both water and land
disposing Characteristic can live in water
Animal dispose
disposing Description Animal not Vegetable
disposing Characteristic has heart
LivingCreature dispose
disposing Description Basic Living Creature
disposing Characteristic is alive
*/

However, if one of these member objects is shared with one or more other objects, the problem becomes more complex and you cannot simply call dispose() . Here, reference counting might be necessary to keep track of the number of objects still accessing a shared object. Here’s what it looks like:

// polymorphism/ReferenceCounting.java
// (c)2017 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information.
// Cleaning up shared member objects

class Shared {
  private int refcount = 0;
  private static long counter = 0; // is long not int to prevent overflow
  private final long id = counter++;

  Shared() {
    System.out.println("Creating " + this);
  }

  public void addRef() {
    refcount++;
  }

  protected void dispose() {
    if (--refcount == 0) System.out.println("Disposing " + this);
  }

  @Override
  public String toString() {
    return "Shared " + id;
  }
}

class Composing {
  private Shared shared;
  private static long counter = 0; // is long not int to prevent overflow
  private final long id = counter++;

  Composing(Shared shared) {
    System.out.println("Creating " + this);
    this.shared = shared;
    this.shared.addRef();
  }

  protected void dispose() {
    System.out.println("disposing " + this);
    shared.dispose();
  }

  @Override
  public String toString() {
    return "Composing " + id;
  }
}

public class ReferenceCounting {
  public static void main(String[] args) {
    Shared shared = new Shared();
    Composing[] composing = {
      new Composing(shared),
      new Composing(shared),
      new Composing(shared),
      new Composing(shared),
      new Composing(shared)
    };
    // - System.out.println("shared.counter:" + shared.counter); //error: counter has private access
    // in Shared
    for (Composing c : composing) {
      c.dispose();
      // - System.out.println("Composing.counter:" + c.counter);// error: counter has private access
      // in Composing
    }
    // - System.out.println("shared.counter:" + shared.counter);
  }
}
/* Output:
Creating Shared 0
Creating Composing 0
Creating Composing 1
Creating Composing 2
Creating Composing 3
Creating Composing 4
disposing Composing 0
disposing Composing 1
disposing Composing 2
disposing Composing 3
disposing Composing 4
Disposing Shared 0
*/

references:

1. On Java 8 - Bruce Eckel

2. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/polymorphism/Frog.java

3. https://github.com/wangbingfeng/OnJava8-Examples/blob/master/polymorphism/ReferenceCounting.java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值