友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第212章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




    start();  

  }  

  public void invertFlag() { runFlag = !runFlag;}  

  public void run() {  

    while (true) {  

     try {  

      sleep(100);  

     } catch (InterruptedException e){}  

     if(runFlag)   

       c2。t。setText(Integer。toString(count++));  

    }  

  }  

}   

  

public class Counter2 extends Applet {  

  TextField t = new TextField(10);  

  private SeparateSubTask sp = null;  

  private Button   

    onOff = new Button(〃Toggle〃);  

    start = new Button(〃Start〃);  

  public void init() {  

    add(t);  

    start。addActionListener(new StartL());  

    add(start);  

    onOff。addActionListener(new OnOffL());  

    add(onOff);  

  }  

  class StartL implements ActionListener {  

    public void actionPerformed(ActionEvent e) {  

      if(sp == null)  

        sp = new SeparateSubTask(Counter2。this);  

    }  

  }  

  class OnOffL implements ActionListener {  

    public void actionPerformed(ActionEvent e) {  

      if(sp != null)  

        sp。invertFlag();  

    }  

  }  

  public static void main(String'' args) {  

    Counter2 applet = new Counter2();  

    Frame aFrame = new Frame(〃Counter2〃);  

    aFrame。addWindowListener(  

      new WindowAdapter() {  

        public void windowClosing(WindowEvent e) {  

          System。exit(0);  

        }  

      });  

    aFrame。add(applet; BorderLayout。CENTER);  

    aFrame。setSize(300;200);  

    applet。init();  



                                                                                               491 


…………………………………………………………Page 493……………………………………………………………

    applet。start();  

    aFrame。setVisible(true);  

  }  

} ///:~  

  

现在,Counter2 变成了一个相当直接的程序,它的唯一任务就是设置并管理用户界面。但假若用户现在按下 

Start 按钮,却不会真正调用一个方法。此时不是创建类的一个线程,而是创建 SeparateSubTask,然后继续 

Counter2 事件循环。注意此时会保存 SeparateSubTask 的句柄,以便我们按下onOff 按钮的时候,能正常地 

切换位于SeparateSubTask 内部的runFlag (运行标志)。随后那个线程便可启动(当它看到标志的时 

候),然后将自己中止(亦可将SeparateSubTask 设为一个内部类来达到这一目的)。  

SeparateSubTask 类是对 Thread 的一个简单扩展,它带有一个构建器(其中保存了 Counter2 句柄,然后通 

过调用 start()来运行线程)以及一个 run()——本质上包含了Counter1。java 的go()内的代码。由于 

SeparateSubTask 知道自己容纳了指向一个 Counter2 的句柄,所以能够在需要的时候介入,并访问 Counter2 

的TestField (文本字段)。  

按下onOff 按钮,几乎立即能得到正确的响应。当然,这个响应其实并不是“立即”发生的,它毕竟和那种 

由“中断”驱动的系统不同。只有线程拥有CPU 的执行时间,并注意到标记已发生改变,计数器才会停止。  

  

1。 用内部类改善代码  

下面说说题外话,请大家注意一下 SeparateSubTask 和 Counter2 类之间发生的结合行为。SeparateSubTask 

同Counter2 “亲密”地结合到了一起——它必须持有指向自己“父”Counter2 对象的一个句柄,以便自己能 

回调和操纵它。但两个类并不是真的合并为单独一个类(尽管在下一节中,我们会讲到Java 确实提供了合并 

它们的方法),因为它们各自做的是不同的事情,而且是在不同的时间创建的。但不管怎样,它们依然紧密 

地结合到一起(更准确地说,应该叫“联合”),所以使程序代码多少显得有些笨拙。在这种情况下,一个 

内部类可以显著改善代码的“可读性”和执行效率:  

  

//: Counter2i。java  

// Counter2 using an inner class for the thread  

import java。awt。*;  

import java。awt。event。*;  

import java。applet。*;  

  

public class Counter2i extends Applet {  

  private class SeparateSubTask extends Thread {  

    int count = 0;  

    boolean runFlag = true;  

    SeparateSubTask() { start(); }  

    public void run() {  

      while (true) {  

       try {  

        sleep(100);  

       } catch (InterruptedException e){}  

       if(runFlag)   

         t。setText(Integer。toString(count++));  

      }  

    }  

  }   

  private SeparateSubTask sp = null;  

  private TextField t = new TextField(10);  

  private Button   

    onOff = new Button(〃Toggle〃);  

    start = new Button(〃Start〃);  

  public void init() {  



                                                                                          492 


…………………………………………………………Page 494……………………………………………………………

    add(t);  

    start。addActionListener(new StartL());  

    add(start);  

    onOff。addActionListener(new OnOffL());  

    add(onOff);  

  }  

  class StartL implements ActionListener {  

    public void actionPerformed(ActionEvent e) {  

      if(sp == null)  

        sp = new SeparateSubTask();  

    }  

  }  

  class OnOffL implements ActionListener {  

    public vo id actionPerformed(ActionEvent e) {  

      if(sp != null)  

        sp。runFlag = !sp。runFlag; // invertFlag();  

    }  

  }  

  public static void main(String'' args) {  

    Counter2i applet = new Counter2i();  

    Frame aFrame = new Frame(〃Counter2i〃);  

    aFrame。addWindowListener(  

      new WindowAdapter() {  

        public void windowClosing(WindowEvent e) {  

          System。exit(0);  

        }  

      });  

    aFrame。add(applet; BorderLayout。CENTER);  

    aFrame。setSize(300;200);  

    applet。init();  

    applet。start();  

    aFrame。setVisible(true);  

  }  

} ///:~  

  

这个SeparateSubTask 名字不会与前例中的 SeparateSubTask 冲突——即使它们都在相同的目录里——因为 

它已作为一个内部类隐藏起来。大家亦可看到内部类被设为private (私有)属性,这意味着它的字段和方 

法都可获得默认的访问权限(run()除外,它必须设为 public,因为它在基础类中是公开的)。除Counter2i 

之外,其他任何方面都不可访问private 内部类。而且由于两个类紧密结合在一起,所以很容易放宽它们之 

间的访问限制。在SeparateSubTask 中,我们可看到invertFlag()方法已被删去,因为 Counter2i 现在可以 

直接访问runFlag。  

此外,注意 SeparateSubTask 的构建器已得到了简化——它现在唯一的用外就是启动线程。Counter2i 对象 

的句柄仍象以前那样得以捕获,但不再是通过人工传递和引用外部对象来达到这一目的,此时的内部类机制 

可以自动照料它。在run()中,可看到对t 的访�
返回目录 上一页 下一页 回到顶部 赞(1) 踩(1)
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!