欢迎来到海淘科技官网 官方微信 官方微博 平面活动官网
微信

网络传播媒介服务提供商

热线电话

021-62677988

海淘新闻
首页 > 新闻列表 > 【建站知识】网站建设程序异常事件

【建站知识】网站建设程序异常事件

发布时间: 2016-08-18 15:47

捕获异常

有些代码必须捕获异常,捕获异常需要进行周密的计划。

如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈的内容。对于图形界面程序(applet和application应用程序),在捕获异常之后,也会打印出堆栈的信息,但程序将返回到用户界面的处理循环中(在调试基于图形界面的程序时,最好保证控制台窗口可见,并且没有被极小化)。

捕获一个异常,必须设置try/catch语句块,如果在try语句块中的任何代码抛出了一个在catch+句中说明的异常类,那么:

1.程序将跳过try语句块的其余代码。

2.程序将执行catch子句中的处理器代码。

如果在try语句块中的代码没有抛出任何异常,那么程序将跳过catch子句。

如果方法中的任何代码抛出了一个在catch+句中没有声明的异常类型,那么这个方法就会立刻退出(期待调用者为这种类型的异常设计了catch子句)。

需要注意,try语句中的大多数代码都很容易理解:读取并处理文本行,直到遇到文件结束符为止。正如在JavaAPI中看到的那样,read方法有可能抛出一个IOException异常。在这种情况下,将跳出整个while循环,进入catch子句,并输出堆栈情况。对于一个普通的程序来说,这样处理异常基本上合乎情理。还有其他的选择吗?

通常,最好的选择是什么也不做,而是将异常传递给调用者。如果read方法出现了错误,就让read方法的调用者去操心!如果采用这种处理方式,就必须声明这个方法可能会抛出一个IOException。

请记住,编译器严格地执行throws说明符。如果调用了一个抛出已检查异常的方法,就必须对它进行处理,或者将它传递出去。

哪种方法更好呢?通常,应该捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常传递出去。如果想将异常传递出去,就必须在方法的首部添加一个throws说明符以便告知调用者这个方法可能会抛出异常。

仔细阅读一下JavaAPI文档,以便知道每个方法可能会抛出哪种异常,然后再决定是自己处理,还是添加到throws列表。对于后一种情况,也不必犹豫。将异常直接交给能够胜任的处理器进行处理要比压制对它的处理更好。

同时请记住,这个规则也有一个例外。如果编写一个覆盖超类的方法,而这个方法又没有抛出异常,那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的thrws说明符中出现超过超类方法所列出的异常类范围。

处理异常

假设在一个Java程序运行期间出现了一个错误。这个错误可能是由于文件包含了错误的信息,或者网络连接出现问题造成的,也有可能是因为使用无效的数组下标,或者试图使用一个没有被赋值引用而造成的。用户期望在出现错误时,程序能够采用一些理智的行为,如果由于出现错误而使得某些操作没有完成,程序应该:返回到一种安全状态,并能够让用户执行一些其他的命令;或者允许用户保存所有操作的结果,并以适当的方式终止程序。

要做到这些并不是一件很容易的事情。其原因是检测(或引发)错误条件的代码通常离那些能够让数据恢复到安全状态,或者能够保存用户的操作结果,并正常地退出程序的代码很远。异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器。为了能够在程序中处理异常情况,必须研究程序中可能会出现的错误和问题,以及哪类问题需要关注。

1.用户输入错误

除了那些不可避免的打字录入外,有些用户喜欢各行其是,不遵守程序的要求。例如,假设有一个用户请求连接一个URL,而语法却不正确。在程序代码中应该对此进行检查,如果没有检查,网络数据包就会给出警告。

2.设备错误

硬件并不总是让它做什么,它就做什么。打印机可能被关掉了。网页可能临时性地不能浏览。在一个任务的处理过程中,硬件经常出现问题。例如,打印机在打印过程中可能没有纸了。

3.物理限制

磁盘满了,可用存储空间已被用完。

4.代码错误

程序方法有可能无法正确的执行。例如,方法可能返回了一个错误的答案,或者错误地调用了其他方法。使用了一个无效的数组下标,试图查找一个在散列表中不存在的数据项以及试图对一个空栈进行退栈操作。

对于方法中出现的错误,传统的处理方式是返回一个特定的错误编码,调用这个方法的方法对其进行分析。例如,对于一个从文件中读取信息的方法来说,如果返回值不是标准字符,而是一个-1,则表示文件结束。这种处理方式对于很多异常状况都是可行的。还有一种表示错误状况的常用返回值是null引用。当希望查询的参数不存在时,这个方法就会返回null。

遗憾的是,并不是在任何情况下都能够返回一个错误编码。有可能无法明确地将有效数据与无效数据加以区分。一个返回整型的方法就不能简单地通过返回-1表示错误,因为-1很可能是一个完全合法的结果。

在Java中,如果某个方法不能够采用正常的途径完整它的任务,就可以通过另外一个路径退出方法。在这种情况下,方法并不返回任何值,而是抛出(throw)一个封装了错误信息的对象。需要注意的是,这个方法将会立刻退出,并不返回任何值。此外,调用这个方法的代码也将无法继续执行,而是,异常处理机制开始搜索能够处理这种异常状况的异常处理器(exceptionhandler),异常具有自己的语法和特定的继承结构。

鼠标事件

如果只希望用户能够点击按钮或菜单,那幺就不需要显式地处理鼠标事件。鼠标操作将由用户界面中的各种组件内部处理。然而,如果希望用户使用鼠标画图,就需要补货鼠标移动点击和拖动事件。

当用户点击鼠标按钮时,将会调用三个监听器方法:鼠标第一次被按下时调用mousepressed;鼠标被释放时调用mousereleased;最后调用mouseclicked。如果只对最终的点击事件感兴趣,就可以忽略前两个方法。用mouseevent类对象作为参数,调用getX和gety方法可以获得鼠标被按下时鼠标指针所在的x和y坐标。要想区分单击,双击和三击,需要使用getclickcount方法。

有些用户界面设计者喜欢让用户采用鼠标点击与键盘修饰符组合(例如,control+shift+click)的方式进行操作。我们感觉这并不是一种值得赞许的方式。如果对此持有不同的观点,可以看一看同时检测鼠标按键和键盘修饰符所带来的混乱。

需要注意,在Windows环境下,使用BUTTON3_DOWN_MASK检测鼠标右键(非主要的)状态。

当鼠标在窗口上移动时,窗口将会收到一连串的鼠标移动事件。请注意:有两个独立的接口mouseListener和mouseMotionListener。这样做有利于提高效率。当用户移动鼠标时,只关心鼠标点击(clicks)的监听器就不会被多余的鼠标移动(moves)所困扰。

动作处理

通常,激活一个命令可以有多种方式,用户可以通过菜单、击键或工具栏上的按钮选择特定的功能。在AWT事件模型中实现这些非常容易:将所有事件 连接到同一个监听器上。例如:假设blueAction是一个动作监听器,它的actionPerformed方法可以将背景颜色改变成蓝色。将一个监听 器对象加到下面几个事件源上:

·标记为Blue的工具栏按钮

·标记为Blue的菜单项

·击键CTRL+B

然后,无论改变背景颜色的命令是通过哪种方式下达的,是点击按钮、菜单选择,还是按下键盘,其操作动作都是一样的。

Swing包提供了一种非常实用的机制来封装命令,并将它们连接到多个事件源,这就是Action接口。一个动作是一个封装下列内容的对象:

·命令的说明(一个文本字符串和一个可选图标);

执行命令所需要的参数(例如,在列举的例子中请求改变的颜色)。

第一个方法是ActionListener接口中很熟悉的一个:实际上,Action接口扩展于ActionListener接口,因此,可以在任何需要ActionListener对象的地方使用Action对象。

接下来的两个方法允许启用或禁用这个动作,并检查这个动作当前是否启用。当一个连接到菜单或工具栏上的动作被禁用时,这个选项就会变成灰色。

putValue和getvalue方法允许存储和检索动作对象中的任意名/值。有两个重要的预定义字符串:Action.NAME和Action.sMALLjcON,用于将动作的名字和图标存储到一个动作对象中。

如果动作对象添加到菜单或工具栏上,它的名称和图标就会被自动地提取出来,并显示在菜单项或工具栏中。SHORT_DESCRiRTION值变成了工具提示。

Action接口的最后两个方法能够让其他对象在动作对象的属性发生变化时得到通告,尤其是菜单或工具栏处罚的动作。例如,如果增加一个菜单,作为动作 对象的属性变更监听器,而这个动作对象随后被禁用,菜单就会被调用,并将动作名称变为灰色。属性变更监听器是一种常用的构造形式,它是JavaBeans 组件模型的一部分。

需要注意,Action一个接口,而不是一个类。实现这个接口的所有类都必须实 现刚才讨论的7个方法。庆幸的是,有一个类实现了这个接口除actionPerformed方法之外的所有方法,它就是AbstractAction个类 存储了所有名/值对,并管理着属性变更监听器。我们可以直接扩展AbstractAction类,并在扩展类中实现actionPerformed方法。

构造器读取动作的名称和图标,为工具提示设置简要说明,将工作设置为监听器。

最后,想要将这个动作对象添加到击键中,以便让用户敲击键盘命令来执行这项动作。为了将动作与击键关联起来,首先需要生成KeyStroke类对象。这 是一个很有用的类,它封装了对键的说明。要想生成一个Keystroke对象不要调用构造器,而是调用KeyStroke类中的静态 getKeyStroke方法:

为了能够理解下一个步骤,需要知道keyboardfocus的概 念。用户界面中可以包含许多按钮、菜单、滚动栏以及其他的组件。当用户敲击键盘时,这个动作会被发送给拥有焦点的组件。通常具有焦点的组件可以明显地察觉 到(但并不总是这样),例如,在Java观感中,具有焦点的按钮在按钮文本周围有一个细的矩形边框。用户可以使用TAB键在组件之间移动焦点。当按下 SPACE键时,就点击了拥有焦点的按钮。还有一些键执行一些其他的动作,例如,按下箭头键可以移动滚动条。

然而,在这里的示例中,并不希望将击键发送给拥有焦点的组件。否则,每个按钮都需要知道如何处理CTRL+Y、CTRL+B和CTRL+R这些组合键。

这是一个常见的问题,Swing设计者给出了一种很便捷的解决方案。每个JComponent有三个输入映射(imput maps),每一个映射的KeyStroke对象都与动作关联。

事件处理基础

对于图形用户界面的程序来说,事件处理是十分重要的。要想实现用户界面,必须掌握Java事件处理的基本方法。

任何支持GUI的操作环境都要不断地监视敲击键盘或点击鼠标这样的事件。操作环境将这些事件报告给正在运行的应用程序。如果有事件产生,每个应用程序将 决定如何对它们作出响应。在VisualBasic这样的语言中,事件与代码之间有着明确的对应关系。程序员对相关的特定事件编写代码,并将这些代码放置 在过程中,通常人们将它们称为事件过程(event procedure)。例如,有一个名为HelpButton的VisualBasic按钮有一个与之关联的HelpButton_Click时间过程。 这个过程中的代码将在点击按钮后执行。每个VisualBasic的GUI组件都响应一个固定的事件集,不可能改变VisualBasic组件响应的事件 集。

另一方面,如果使用像原始的C这样的语言进行事件驱动的程序设计,那就需要编写代码来 不断地检查事件队列,以便查询操作环境报告的内容(通常这些代码被放置在包含很多switch语句的循环体申)。显然,这种方式编写的程序可读性很差,而 且在有些情况下,编码的难度也非常大。它的好处在于响应的事件不受限制,而不像VisualBasic这样的语言,将事件队列对程序员隐藏起来。

Java程序设计环境折中了VisualBasic与原始C的事件处理方式,因此,它既有着强大的功能,又具有一定的复杂性。在AWT所知的事件范围 内,完全可以控制事件从事件源(event source)例如,按钮或滚动条,到事件监听器(event listener)的传递过程,并将任何对象指派给事件监听器。不过事实上,应该选择一个能够便于响应事件的对象。这种事件委托模型(event delegation model)与VisualBasic那种预定义监听器模型比较起来更加灵活。

事件源有一些向其注册事件监听器的方法。当某个事件源产生事件时,事件源会向为事件注册的所有事件监听器对象发送一个通告。

像Java这样的面向对象语言,都将事件的相关信息封装在一个事件对象(event object)中,在Java中,所有的事件对象都最终派生于java.util.EventObject类。当然,每个事件类型还有子类,例 如,ActionEvent和WindowEvent。

不同的事件源可以产生不同类别的事件。例如,按钮可以发送一个ActionEvent对象,而窗扣可以发送WindowEvent对象。

综上所述,下面给出AWT事件处理机制的概要:

监听器对象是一个实现了特定监听器接口(listener interface)的类的实例。

事件源是一个能够注册监听器对象并发送事件对象的对象。

当事件发生时,事件源将事件对象传递给所有注册的监听器。

监听器对象将利用事件对象中的信息决定如何对事件做出响应。

相关文章:

版权所有 @ 2007-2023上海海淘信息科技有限公司 沪ICP备11050025号-4