77.JAVA编程思想——模拟垃圾回收

77.JAVA编程思想——模拟垃圾回收

这个问题的本质是若将垃圾丢进单个垃圾筒,事实上是未经分类的。但在以后,某些特殊的信息必须恢复,以便对垃圾正确地归类。在最开始的解决方案中,RTTI 扮演了关键的角色。这并不是一种普通的设计,因为它增加了一个新的限制。正是这个限制使问题变得非常有趣——它更象我们在工作中碰到的那些非常麻烦的问题。这个额外的限制是:垃圾抵达垃圾回收站时,它们全都是混合在一起的。程序必须为那些垃圾的分类定出一个模型。这正是RTTI 发挥作用的地方:我们有大量不知名的垃圾,程序将正确判断出它们所属的类型。

1     代码

import java.util.*;

import java.io.*;

abstract class Trash {

    private doubleweight;

 

    Trash(double wt) {

        weight = wt;

    }

    abstract doublevalue();

    double weight() {

        return weight;

    }

    // Sums thevalue of Trash in a bin:

    static voidsumValue(Vector bin) {

        Enumeration e = bin.elements();

        double val = 0.0f;

        while (e.hasMoreElements()) {

            // One kind of RTTI:

            // A dynamically-checked cast

            Trash t = (Trash) e.nextElement();

            // Polymorphism in action:

            val += t.weight() * t.value();

            System.out.println("weight of "+

            // Using RTTI to get type

            // information about the class:

                    t.getClass().getName() + " = " + t.weight());

        }

        System.out.println("Total value = " + val);

    }

}

 

class Aluminum extends Trash {

    static doubleval= 1.67f;

 

    Aluminum(double wt) {

        super(wt);

    }

 

    double value() {

        return val;

    }

 

    static voidvalue(doublenewval){

        val = newval;

    }

}

 

class Paper extends Trash {

    static doubleval= 0.10f;

 

    Paper(double wt) {

        super(wt);

    }

 

    double value() {

        return val;

    }

 

    static voidvalue(doublenewval){

        val = newval;

    }

}

 

class Glass extends Trash {

    static doubleval= 0.23f;

 

    Glass(double wt) {

        super(wt);

    }

 

    double value() {

        return val;

    }

 

    static voidvalue(doublenewval){

        val = newval;

    }

}

 

public class RecycleA {

    public staticvoidmain(String[] args){

        Vector bin = new Vector();

        // Fill up the Trash bin:

        for (int i = 0; i < 30; i++)

            switch ((int) (Math.random() * 3)) {

            case 0:

                bin.addElement(new Aluminum(Math.random()* 100));

                break;

            case 1:

                bin.addElement(new Paper(Math.random()* 100));

                break;

            case 2:

                bin.addElement(new Glass(Math.random()* 100));

            }

        Vector glassBin = new Vector(), paperBin = new Vector(), alBin = new Vector();

        Enumeration sorter = bin.elements();

        // Sort the Trash:

        while (sorter.hasMoreElements()) {

            Object t = sorter.nextElement();

            // RTTI to show class membership:

            if (t instanceofAluminum)

                alBin.addElement(t);

            if (t instanceofPaper)

                paperBin.addElement(t);

            if (t instanceofGlass)

                glassBin.addElement(t);

        }

        Trash.sumValue(alBin);

        Trash.sumValue(paperBin);

        Trash.sumValue(glassBin);

        Trash.sumValue(bin);

    }

} /// :~

输出:

weightof Aluminum = 40.532515411743795

weightof Aluminum = 83.38919865473446

weightof Aluminum = 73.84371640964957

weightof Aluminum = 10.474970990053

weightof Aluminum = 13.224867897242598

weightof Aluminum = 22.354321379716012

weightof Aluminum = 34.105686597783915

weightof Aluminum = 19.742978223720296

Totalvalue = 497.1059740184192

weightof Paper = 24.70794232333027

weightof Paper = 2.8129388934932553

weightof Paper = 59.3531424871936

weightof Paper = 51.30414548333662

weightof Paper = 11.990721589197884

weightof Paper = 16.510872726252746

weightof Paper = 25.420046775288142

weightof Paper = 61.07763842376982

weightof Paper = 14.077079318003804

Totalvalue = 26.725453200226895

weightof Glass = 72.73164348253516

weightof Glass = 5.011931780096724

weightof Glass = 29.81602815752583

weightof Glass = 22.072368824629862

weightof Glass = 90.15064650452305

weightof Glass = 75.33577784692417

weightof Glass = 51.91046328199902

weightof Glass = 98.00518661238358

weightof Glass = 93.25291794461366

weightof Glass = 97.80335165495947

weightof Glass = 84.00561113051397

weightof Glass = 95.97658239820241

weightof Glass = 55.76586894783563

Totalvalue = 200.52283070794394

weightof Glass = 72.73164348253516

weightof Paper = 24.70794232333027

weightof Aluminum = 40.532515411743795

weightof Aluminum = 83.38919865473446

weightof Paper = 2.8129388934932553

weightof Paper = 59.3531424871936

weightof Paper = 51.30414548333662

weightof Aluminum = 73.84371640964957

weightof Aluminum = 10.474970990053

weightof Glass = 5.011931780096724

weightof Glass = 29.81602815752583

weightof Aluminum = 13.224867897242598

weightof Glass = 22.072368824629862

weightof Glass = 90.15064650452305

weightof Paper = 11.990721589197884

weightof Glass = 75.33577784692417

weightof Aluminum = 22.354321379716012

weightof Paper = 16.510872726252746

weightof Glass = 51.91046328199902

weightof Glass = 98.00518661238358

weightof Glass = 93.25291794461366

weightof Paper = 25.420046775288142

weightof Glass = 97.80335165495947

weightof Aluminum = 34.105686597783915

weightof Aluminum = 19.742978223720296

weightof Glass = 84.00561113051397

weightof Paper = 61.07763842376982

weightof Paper = 14.077079318003804

weightof Glass = 95.97658239820241

weightof Glass = 55.76586894783563

Totalvalue = 724.35425792659

其中创建了几个Vector 对象,用于容纳Trash 句柄。当然,Vector 实际容纳的是Object(对象),所以它们最终能够容纳任何东西。之所以要它们容纳Trash(或者从Trash 衍生出来的其他东西),唯一的理由是我们需要谨慎地避免放入除Trash 以外的其他任何东西。如果真的把某些“错误”的东西置入Vector,那么不会在编译期得到出错或警告提示——只能通过运行期的一个违例知道自己已经犯了错误。

Trash 句柄加入后,它们会丢失自己的特定标识信息,只会成为简单的Object 句柄(上溯造型)。然而,由于存在多形性的因素,所以在我们通过Enumerationsorter 调用动态绑定方法时,一旦结果Object 已经造型回Trash,仍然会发生正确的行为。sumValue()也用一个Enumeration 对Vector 中的每个对象进行操作。

表面上持,先把Trash 的类型上溯造型到一个集合容纳基础类型的句柄,再回过头重新下溯造型,这似乎是一种非常愚蠢的做法。为什么不只是一开始就将垃圾置入适当的容器里呢?(事实上,这正是拨开“回收”一团迷雾的关键)。在这个程序中,我们很容易就可以换成这种做法,但在某些情况下,系统的结构及灵活性都能从下溯造型中得到极大的好处。该程序已满足了设计的初衷:它能够正常工作!只要这是个一次性的方案,就会显得非常出色。但是,真正有用的程序应该能够在任何时候解决问题。所以必须问自己这样一个问题:“如果情况发生了变化,它还能工作吗?”举个例子来说,厚纸板现在是一种非常有价值的可回收物品,那么如何把它集成到系统中呢(特别是程序很大很复杂的时候)?由于前面在switch 语句中的类型检查编码可能散布于整个程序,所以每次加入一种新类型时,都必须找到所有那些编码。若不慎遗漏一个,编译器除了指出存在一个错误之外,不能再提供任何有价值的帮助。

RTTI 在这里使用不当的关键是“每种类型都进行了测试”。如果由于类型的子集需要特殊的对待,所以只寻找那个子集,那么情况就会变得好一些。但假如在一个switch 语句中查找每一种类型,那么很可能错过一个重点,使最终的代码很难维护。在下一节中,大家会学习如何逐步对这个程序进行改进,使其显得越来越灵活。这是在程序设计中一种非常有意义的例子。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值