按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
对本书余下部分而言,匿名内部类将通常被使用在窗口接收器中。
3。 将程序片封装到JAR 文件里
一个重要的 JAR 应用就是完善程序片的装载。在Java 1。0 版中,人们倾向于试法将它们的代码填入到单个的
程序片类里,因此客户只需要单个的服务器就可适合下载程序片代码。但这不仅使结果凌乱,难以阅读(当
然维护也然)程序,但类文件一直不能压缩,因此下载从来没有快过。
JAR 文件将我们所有的被压缩的类文件打包到一个单个儿的文件中,再被浏览器下载。现在我们不需要创建
一个糟糕的设计以最小化我们创建的类,并且用户将得到更快地下载速度。
仔细想想上面的例子,这个例子看起来像 Button2NewB,是一个单类,但事实上它包含三个内部类,因此共
有四个。每当我们编译程序,我会用这行代码打包它到一个JAR 文件:
jar cf Button2NewB。jar *。class
这是假定只有一个类文件在当前目录中,其中之一来自Button2NewB。java (否则我们会得到特别的打包)。
现在我们可以创建一个使用新文件标签来指定 JAR 文件的HTML 页,如下所示:
Button2NewB Example Applet
415
…………………………………………………………Page 417……………………………………………………………
与HTML 文件中的程序片标记有关的其他任何内容都保持不变。
13。16。4 再研究一下以前的例子
为注意到一些利用新事件模型的例子和为学习程序从老到新事件模型改变的方法,下面的例子回到在本章第
一部分利用事件模型来证明的一些争议。另外,每个程序包括程序片和应用程序现在都可以借助或不借助浏
览器来运行。
1。 文本字段
这个例子同 TextField1。java 相似,但它增加了显然额外的行为:
//: TextNew。java
// Text fields with Java 1。1 events
import java。awt。*;
import java。awt。event。*;
import java。applet。*;
public class TextNew extends Applet {
Button
b1 = new Button(〃Get Text〃);
b2 = new Button(〃Set Text〃);
TextField
t1 = new TextField(30);
t2 = new TextField(30);
t3 = new TextField(30);
String s = new String();
public void init() {
b1。addActionListener(new B1());
b2。addActionListener(new B2());
t1。addTextListener(new T1());
t1。addActionListener(new T1A ());
t1。addKeyListener(new T1K());
add(b1);
add(b2);
add(t1);
add(t2);
add(t3);
}
class T1 implements TextListener {
public void textValueChanged(TextEvent e) {
t2。setText(t1。getText());
}
}
class T1A implements ActionListener {
private int count = 0;
public void actionPerformed(ActionEvent e) {
t3。setText(〃t1 Action Event 〃 + count++);
416
…………………………………………………………Page 418……………………………………………………………
}
}
class T1K extends KeyAdapter {
public void keyTyped(KeyEvent e) {
String ts = t1。getText();
if(e。getKeyChar() ==
KeyEvent。VK_BACK_SPACE) {
// Ensure it's not empty:
if( ts。length() 》 0) {
ts = ts。substring(0; ts。length() 1);
t1。setText(ts);
}
}
else
t1。setText(
t1。getText() +
Character。toUpperCase(
e。getKeyChar()));
t1。setCaretPosition(
t1。getText()。length());
// Stop regular character from appearing:
e。consume();
}
}
class B1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
s = t1。getSelectedText();
if(s。length() == 0) s = t1。getText();
t1。setEditable(true);
}
}
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
t1。setText(〃Inserted by Button 2: 〃 + s);
t1。setEditable(false);
}
}
public static void main(String'' args) {
TextNew applet = new TextNew();
Frame aFrame = new Frame(〃TextNew〃);
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);
}
417
…………………………………………………………Page 419……………………………………………………………
} ///:~
当TextField t1 的动作接收器被激活时,TextField t3 就是一个需要报告的场所。我们注意到仅当我们按
下“enter”键时,动作接收器才会为“TextField”所激活。
TextField t1 附有几个接收器。T1 接收器从 t1 复制所有文字到t2,强制所有字符串转换成大写。我们会发
现这两个工作同是进行的,并且如果我们增加 T1K 接收器后我们再增加T1 接收器,它就不那么重要:在文字
字段内的所有的字符串将一直被强制变为大写。这看起来键盘事件一直在文字组件事件前被激活,并且如果
我们需要保留t2 的字符串原来输入时的样子,我们就必须做一些特别的工作。
T1K 有着其它的一些有趣的活动。我们必须测试backspace (因为我们现在控制着每一个事件)并执行删除。
caret 必须被明确地设置到字段的结尾;否则它不会像我们希望的运行。最后,为了防止原来的字符串被默
认的机制所处理,事件必须利用为事件对象而存在的consume()方法所“耗尽”。这会通知系统停止激活其
余特殊事件的事件处理器。
这个例子同样无声地证明了设计内部类的带来的诸多优点。注意下面的内部类:
class T1 implements TextL istener {
public void textValueChanged(TextEvent e) {
t2。setText(t1。getText());
}
}
t1 和 t2 不属于 T1 的一部分,并且到目前为止它们都是很容易理解的,没有任何的特殊限制。这是因为一个
内部类的对象能自动地捕捉一个句柄到外部的创建它的对象那里,因此我们可以处理封装类对象的方法和内
容。正像我们看到的,这十分方便(注释⑥)。
⑥:它也解决了“回调”的问题,不必为 Java 加入任何令人恼火的“方法指针”特�