ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:26.41KB ,
资源ID:20093261      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20093261.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(应用建模语言JML改进Java程序Word文档下载推荐.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

应用建模语言JML改进Java程序Word文档下载推荐.docx

1、 能够更为精确地描述这些代码是做什么的 能够高效地发现和修正程序中的bug 可以在应用程序升级时降低引入bug的机会 可以提早发现客户代码对类的错误使用 可以提供与应用程序代码完全一致的JML格式的文档 JML标记总是在Java注释的内部,所以对正常编译的代码没有任何影响。如果你想比较一下普通的类和使用了JML的类有什么差别的话,你可以使用一个开源的JML编译器。用JML编译器编译的代码如果没有实现JML规范所要求的事项,运行时就会抛出一个JML异常。这个特性不仅可以帮助我们捕获代码中的bug,而且可以确保JML形式的文档可以与程序代码高度一致。使用开放源代码的Jakarta Commons

2、Collection Component (JCCC)项目中的PriorityQueue接口和BinaryHeap 类来演示JML的各种性质。在这里你可以找到使用了JML标记完整的这个两个文件。、确定类实现的规范本文中使用的代码包括开源项目JCCC中的PriorityQueue 接口。接口嘛,自然是声明了一些方法的签名,包括方法的参数类型、返回值的类型,并不涉及方法的实现。一般情况下或者只是按照Java语法要求的话,实现接口的类只要实现了接口中定义的各个方法即可,不论实现的方式是多么地离奇古怪。我们并不想这样,我们希望能够确定一个行为规范,所有实现这个接口的类都用我们指定的方式来实现这个接口中

3、定义的方法。通过使用JML我们可以做到这一点。考虑一下PriorityQueue接口的pop()方法,对于优先级队列来说,pop()方法应该有什么样的功能要求?最起码应该有三个:第一,如果要调用pop()方法,队列中至少要有一个元素;第二,该方法应该返回队列中优先级最高的那个元素;第三,该方法应该从队列中删除返回的那个元素。下面代码段显示了表示满足第一个要求的JML标记:代码段1 pop()方法功能规范的JML标记/* public normal_behavior requires ! isEmpty(); */Object pop() throws NoSuchElementExceptio

4、n;前面已经提到,JML标记是写在Java代码的注释中的。包含JML标记的多行注释以/* 开头,JML忽略任何以开头的空行。如果是单行的话,你也可以使用/这种标记。这里JML注释中public关键字与Java中的public意思是一样的,它表示程序中其他所有的类都要遵循这个JML要求。Public要求只能应用在public方法和public成员变量上。JML同样有private-、 protected-、 以及 package-级别的作用域。同样,这些作用域的规则与Java语言中作用域的规则非常相似。这里normal_behavior关键字的意思是,这个JML要求表示这是一种正常情况,运行时不

5、会抛出异常。后面,我们会描述异常行为是怎么被界定的。、前置条件和后置条件JML关键字requires用来表示前置条件,前置条件表示调用一个方法前必须满足的一些要求。上面代码段中包含一个前置条件,它要求调用pop()方法的前提就是isEmpty()方法返回false,也就是说要求这个队列至少含有一个元素。一个方法的后置条件规范表示一个方法的责任,也就是说当这个方法返回时,它必须满足这个后置条件的要求。在我们上面的例子中,pop()方法应该返回队列中优先级最高的元素。我们希望指定一个后置条件要求JML在运行时检查是否满足这个事实。要做到这一点,我们必须跟踪所有添加到这个优先级队列中的元素,这样我们

6、就可以判断pop()方法应该返回哪一个元素。怎么做呢?你可能会考虑在PriorityQueue接口中加入一个成员变量来存储队列中元素的值,不过这样做有两个问题: PriorityQueue是一个接口,它可能有各种不同具体的实现方式,比如说binary heap、Fibonacci heap或者calendar queue等等,它要与它的各种实现一致,况且JML标记不应该涉及到任何具体的实现细节。 作为一个接口,PriorityQueue只能拥有静态成员变量。为了处理这种情况,JML引入了一个叫做模型域(model fields)的概念。、模型域模型域类似于成员变量,它只能被应用到行为规范中。这

7、是一个PriorityQueue中声明模型域的例子:/ public model instance JMLObjectBag elementsInQueue;这个声明的意思是说这里有一个叫做elementsInQueue的模型域,它的类型是JMLObjectBag (这个数据类型是在JML中定义的)。instance关键字表示虽然这个域是定义在接口中,可是任何实现这个接口的类都拥有一个单独的、非静态的elementsInQueue域。与其他JML标记一样,这个声明也是出现在注释中的,所以常规的Java代码是不能使用这个elementsInQueue变量的。在程序运行的时候,是没有任何对象拥有一

8、个叫做elementsInQueue的成员变量的。elementsInQueue 存储添加到优先级队列的元素的值,下面的代码段显示pop()方法如何使用elementsInQueue:代码段2 在pop()的后置条件中使用模型域 ensures elementsInQueue.equals(JMLObjectBag) old(elementsInQueue) .remove(result) & result.equals(old(peek();ensures关键字表示后面跟着的是pop()方法返回时必须满足的后置条件。result是一个JML关键字,它等于pop()方法的返回值。old()是一

9、个JML函数,它返回pop()方法调用之前参数的值。这个ensures语句包含了两个后置条件。第一,pop()方法返回的那个元素必须要从elementsInQueue删除。第二,这个返回值要与peek()方法返回的值一致。不过虽然用JML定义行为规范的时候不需要考虑执行效率,程序运行时JML断言检查却是很重要的。所以开启断言检查时程序的运行可能会有性能的压力。、行为规范与实现使用一个包来存储队列中的元素,然后检查每一个元素找出优先级最高的那一个会让人觉得效率不高。不过这只是行为规范的一部分,而不会涉及到实现。行为规范的作用在于描述 PriorityQueue的行为接口,也就是说规定了使用 Pr

10、iorityQueue的客户代码所能依赖的外部行为。PriorityQueue接口的各个具体实现只要可以满足这个行为规范的要求,就可以使用任何更为高效的方法。比如说,JCCC有一个实现这个接口的 BinaryHeap类,它的实现方式就是使用一个存储在数组中的 binary heap 。、类级别的不变量我们现在已经看到JML能够让我们规定方法的前置条件和后置条件,它同样也允许我们指定类级别的不变量。类级别的不变量指的是进入和退出一个类中每个方法都必须满足的条件。比方说吧,/ public instance invariant elementsInQueue != null; 就是Priority

11、Queue的一个不变量,它的意思是任何实现PriorityQueue的类一旦被实例化,elementsInQueue的值就不能是null。、量词(Quantification)这里量词的意思与逻辑学上的量词意思相近,而不是普通意义上理解的量词。在上面pop()方法的行为规范中,我们说它的返回值要等于peek()方法的返回值,不过我们并没有看到关于peek()方法的规范。PriorityQueue中peek()方法的行为规范请看下面的代码:代码段3 PriorityQueue 中peek()方法的行为规范 ensures elementsInQueue.has(result);/* pure *

12、/ Object peek() throws NoSuchElementException;JML标记要求只有当队列中至少含有一个元素的时候,才能调用peek()方法,同时他还要求方法的返回值必须在elementsInQueue之内,也就是说,这个返回值一定是这个队列中的一个元素。注释/* pure */ 表明peek()方法是一个纯方法(pure method),纯方法是指没有副作用的方法。JML中只允许使用纯方法进行断言确认,所以我们把peek()声明为纯方法,这样我们就可以在pop()方法的后置条件中使用peek()方法。大家肯定想知道,为什么JML只允许使用纯方法进行断言确认?问题是这

13、样的,如果JML允许使用非纯方法进行断言确认的话,我们稍不注意就会写出有副作用的行为规范。比如说可能会有这么一种情况,开启了断言确认以后,我们的代码正确无误,可是如果禁止了断言确认后,我们的代码却不能运行了,或运行出错了。这样当然不行!后面,我们还会进一步讨论副作用的问题。、关于继承JML行为规范可以被子类(含子接口)或者是实现接口的类所继承,这一点与J2SE1.4中断言有所不同。JML关键字 also表示当前定义的行为规范与祖先类或被实现的接口中所定义的行为规范一起作用。因而,在 PriorityQueue接口定义的 peek()方法的行为规范同样适用于 BinaryHeap类中的 peek

14、()方法。这个就意味着,虽然在 BinaryHeap.peek()的行为规范中没有明确定义, BinaryHeap.peek()的返回值也必须在 elementsInQueue当中。、大顶堆和小顶堆大顶堆和小顶堆是数据结构里面的概念,分别表示堆排序方法的不同实现方式。堆排序是一种通过调整二叉树进行排序的方法。上面我们给peek()定义的行为规范明显缺少了一块,那就是我们根本没有要求它返回的那个元素具有最大的优先级。显然,JCCC的PriorityQueue接口既可以用于大顶堆,也可以用于小顶堆。大顶堆和小顶堆的表现是有些差别的,在小顶堆中优先级最高的元素值最小,而大顶堆中优先级最高的元素值最大

15、。因为PriorityQueue并不知道自己被用来进行大顶堆排序还是小顶堆排序,所以指定返回哪个元素的规范必须在实现PriorityQueue接口的类中进行定义。在JCCC 中,类 BinaryHeap实现了PriorityQueue接口。BinaryHeap允许使用它的客户代码在构造函数中通过一个参数来指定排序方案,也就是通过参数来指定是通过大顶堆方式排序还是通过小顶堆方式排序。我们使用一个boolean模型变量isMinimumHeap来判断BinaryHeap的排序方式是大顶堆还是小顶堆。下面的例子是BinaryHeap使用isMinimumHeap给peek()方法定义的行为规范:代码

16、段4 BinaryHeap 类中peek()方法的行为规范 also (isMinimumHeap = (forall Object obj; elementsInQueue.has(obj); compareObjects(result, obj) = 0);public Object peek() throws NoSuchElementException、使用量词上面代码段4中的后置条件包含两个部分,分别用于大顶堆和小顶堆的情况。“=”符号的意思是包含(译者注:这个包含与逻辑学中包含的意思一致)。x = y 当且仅当y为真或x为假时取真值。对于小顶堆排序来说,适用下面所列的代码:(for

17、all Object obj; elementsInQueue.has(obj); compareObjects(result, obj) (result = (Comparable) a).compareTo(b) & (comparator != null) = (result = pare(a, b); public pure model int compareObjects(Object a, Object b) if (m_comparator = null) return (Comparable) a).compareTo(b); else return m_pare(a, b);

18、 compareObjects方法的定义中使用了另外一个关键字model,它的意思是compareObjects方法是一个模型方法。模型方法是只能用在行为规范中的JML方法。模型方法定义在Java的注释中,所以常规的Java代码不能使用。如果BinaryHeap类的客户代码指定了一个特殊的Comparator用来进行比较的话,m_comparator就指向那个Comparator,否则m_comparator的值就是null。compareObjects()方法检查m_comparator的值,然后采用适当的方法进行元素间的比较。、模型域如何取值在代码段4中我们讨论了peek()方法的后置条件

19、。这个条件保证peek()方法的返回值的优先级大于或者等于模型域elementsInQueue中所有的元素的优先级。那么有一个问题,像elementsInQueue这样的模型域如何取值?前置条件、后置条件和不变量都是没有副作用的,所以不能使用它们来设置模型域的值。JML使用一个represents语句把模型域与具体的实现域关联起来。比如下面的represents语句用来给模型域isMinimumHeap赋值:/ private represents isMinimumHeap - m_isMinHeap;这个语句的意思是模型域isMinimumHeap的值等于m_isMinHeap的值,其中,

20、m_isMinHeap是BinaryHeap类中一个私有的布尔变量。 一旦需要用到isMinimumHeap的值,JML就会把m_isMinHeap的值赋给它。represents语句并没有限制-右边必须是成员变量。比如说,下面是elementsInQueue的represents语句:代码段6 elementsInQueue 的represents语句/* private represents elementsInQueue- JMLObjectBag.convertFrom( Arrays.asList(m_elements) .subList(1, m_size + 1);从这里我们可以

21、看出,elementsInQueue的元素就是数组m_elements从第一个元素到第m_size个元素共m_size个元素构成的列表,其中数组m_elements是BinaryHeap的一个私有成员,用来存储优先级队列中的元素,m_size是m_elements中正在使用的元素的个数。类BinaryHeap没有使用m_elements0,这样可以简化对于索引的操作。JMLObjectBag.convertFrom()的作用是把一个List结构转化为一个elementsInQueue所需要的JMLObjectBag结构。这样一旦JML运行时进行断言检查的时候需要elementsInQueue的

22、值,系统就会计算represents 语句-符号右边的代码并进行求值。二、副作用、副作用产生的原因:大家回忆一下代码段2中pop()方法的后处理代码:ensureselementsInQueue.equals(JMLObjectBag) old(elementsInQueue) .remove(result) &result.equals(old(peek();这里我们说有一个副作用,那就是在从elementsInQueue删除一个元素的时候会有副作用。事实上,这里还可能有其他的副作用。比方说,一个pop()方法的具体实现中如果修改了m_isMinHeap的值,那么就把排序方法从一个小顶堆变成

23、了大顶堆。只要这种修改能够返回正确结果,就不会引起运行期间的断言检查异常,可是这个却事实上削弱了JML行为规范的作用。我们可以加强后置条件,不允许除了修改elementsInQueue以外的任何改变,请看下面的代码:代码断7 加强的后置条件result.equals(old(peek() &isMinimumHeap = old(isMinimumHeap) &comparator = old(comparator);从中我们可以看出,通过加入形如x = old(x)的语句,我们可以消除变量x发生改变的副作用。可是有一个问题,如果用这种办法,每一个方法在它的后置条件都要为每一个变量加上这么一句,这样就会导致行为规范的混乱。而且如果我们给一个类增加一个成员的变量的话,那么我们就得在这个类的所有方法的后处理规范中增加一句,这将让维护变得异常困难。、解决方法:JML通过引入assignable语句提供了一种更好地解决方案。使用assignable语句,我们可以这样完成pop()方法的后置条件:代码段8 在方法的行为规范中使用assignable语句 assignable elementsInQueue;只有在assignable语句中列出的变量才能在一个方法的实现中修改。上面pop()方法的assignable语句的

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1