<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自由飛翔

    我在仰望,java之上

    統(tǒng)計

    留言簿(2)

    我關(guān)注的blog

    閱讀排行榜

    評論排行榜

    轉(zhuǎn)載:java斷言Assertion

    文章來源:http://www.cnblogs.com/woodslee/articles/165669.html 

    一、 Assertion的語法和語義

    J2SE 1.4在語言上提供了一個新特性,就是assertion(斷言)功能,它是該版本在Java語言方面最大的革新。在軟件開發(fā)中,assertion是一種經(jīng)典的調(diào)試、測試方式,本文將深入解析assertion功能的使用以及其設(shè)計理念,并給出相關(guān)的例子 。

    assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語言中都支持這種機制,如CC++Eiffel等,但是支持的形式不盡相同,有的是通過語言本身、有的是通過庫函數(shù)等。另外,從理論上來說,通過assertion方式可以證明程序的正確性,但是這是一項相當復(fù)雜的工作,目前還沒有太多的實踐意義。

    在實現(xiàn)中,assertion就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經(jīng)處于不正確的狀態(tài)下,系統(tǒng)將給出警告并且退出。一般來說,assertion用于保證程序最基本、關(guān)鍵的正確性assertion檢查通常在開發(fā)和測試時開啟。為了提高性能,在軟件發(fā)布后,assertion檢查通常是關(guān)閉的。下面簡單介紹一下Javaassertion的實現(xiàn)。

    Ø         語法

    在語法上,為了支持assertionJava增加了一個關(guān)鍵字assert。它包括兩種表達式,分別如下:

    1.      assert expression1;

    2.      assert expression1: expression2;

    expression1表示一個boolean表達式,expression2表示一個基本類型、表達式或者是一個Object,用于在失敗時輸出錯誤信息。

    下面是一些Assert的例子。

    1.      assert  0 < value;

    2.      assert  0 < value:"value="+value;

    3.      assert  ref != null:"ref doesn't equal null";

    4.      assert  isBalanced();

    在運行時,如果關(guān)閉了assertion功能,這些語句將不起任何作用。如果打開了assertion功能,那么expression1的值將被計算,如果它的值為false,該語句強拋出一個AssertionError對象。如果assertion語句包括expression2參數(shù),程序?qū)⒂嬎愠?span lang="EN-US" style="line-height: 1.5; ">expression2的結(jié)果,然后將這個結(jié)果作為AssertionError的構(gòu)造函數(shù)的參數(shù),來創(chuàng)建AssertionError對象,并拋出該對象;如果expression1值為trueexpression2將不被計算。

    一種特殊情況是,如果在計算表達式時,表達式本身拋出Exception,那么assert將停止運行,而拋出這個Exception

    Ø         編譯

    由于assert是一個新關(guān)鍵字,使用老版本的JDK是無法編譯帶有assert的源程序。因此,我們必須使用JDK1.4(或者更新)Java編譯器,在使用Javac命令時,我們必須加上-source 1.4作為參數(shù)。-source 1.4表示使用JDK 1.4版本的方式來編譯源代碼,否則編譯就不能通過,因為缺省的Javac編譯器使用JDK1.3的語法規(guī)則。

    Ø         運行

    由于帶有assert語句的程序運行時,使用了新的ClassLoaderClass類,因此,這種程序必須在JDK1.4(或者更高版本)JRE下運行,而不能在老版本的JRE下運行。

    由于我們可以選擇開啟assertion功能,或者不開啟,另外我們還可以開啟一部分類或包的assertion功能,所以運行選項變得有些復(fù)雜。通過這些選項,我們可以過濾所有我們不關(guān)心的類,只選擇我們關(guān)心的類或包來觀察。下面介紹兩類參數(shù):

    1.      參數(shù) -esa 和 -dsa
    它們含義為開啟(關(guān)閉)系統(tǒng)類的assertion功能。由于新版本的Java的系統(tǒng)類中,也使了assertion語句,因此如果用戶需要觀察它們的運行情況,就需要打開系統(tǒng)類的assertion功能 ,我們可使用-esa參數(shù)打開,使用 -dsa參數(shù)關(guān)閉。
    -esa
    -dsa的全名為-enablesystemassertions-disenablesystemassertions,全名和縮寫名有同樣的功能。

    2.      參數(shù) -ea-ea
    它們含義為開啟(關(guān)閉)用戶類的assertion功能:通過這個參數(shù),用戶可以打開某些類或包的assertion功能,同樣用戶也可以關(guān)閉某些類和包的assertion功能。打開assertion功能參數(shù)為-ea;如果不帶任何參數(shù),表示打開所有用戶類;如果帶有包名稱或者類名稱,表示打開這些類或包;如果包名稱后面跟有三個點,代表這個包及其子包;如果只有三個點,代表無名包。關(guān)閉assertion功能參數(shù)為-da,使用方法與-ea類似。
    -ea
    -da的全名為-enableassertions-disenableassertions,全名和縮寫名有同樣的功能。下面表格表示了參數(shù)及其含義,并有例子說明如何使用。

    參數(shù)

    例子

    說明

    -ea

    java -ea

    打開所有用戶類的assertion

    -da

    java -da

    關(guān)閉所有用戶類的assertion

    -ea:<classname>

    java -ea:MyClass1

    打開MyClass1assertion

    -da:<classname>

    java -da: MyClass1

    關(guān)閉MyClass1assertion

    -ea:<packagename>

    java -ea:pkg1

    打開pkg1包的assertion

    -da:<packagename>

    java -da:pkg1

    關(guān)閉pkg1包的assertion

    -ea:...

    java -ea:...

    打開缺省包(無名包)assertion

    -da:...

    java -da:...

    關(guān)閉缺省包(無名包)assertion

    -ea:<packagename>...

    java -ea:pkg1...

    打開pkg1包和其子包的assertion

    -da:<packagename>...

    java -da:pkg1...

    關(guān)閉pkg1包和其子包的assertion

    -esa

    java -esa

    打開系統(tǒng)類的assertion

    -dsa

    java -dsa

    關(guān)閉系統(tǒng)類的assertion

    綜合使用

    java -dsa:MyClass1:pkg1

    關(guān)閉MyClass1pkg1包的assertion

    3.      
    其中...代表,此包和其子包的含義。例如我們有兩個包為pkg1pkg1.subpkg。那么pkg1...就代表pkg1pkg1.subpkg兩個包。
    另外,Java為了讓程序也能夠動態(tài)開啟和關(guān)閉某些類和包的assertion功能,Java修該了ClassClassLoader的實現(xiàn),增加了幾個用于操作assertAPI。下面簡單說明一下幾個API的作用。
    ClassLoader
    類中的幾個相關(guān)的API:
      setDefaultAssertionStatus:用于開啟/關(guān)閉assertion功能
      setPackageAssertionStatus:用于開啟/關(guān)閉某些包的assertion功能
      setClassAssertionStatus: 用于開啟/關(guān)閉某些類的assertion功能
      clearAssertionStatus:用于關(guān)閉assertion功能

    二、 Assertion的設(shè)計問題

    首先,我們認為assertion是必要的。因為,如果沒有統(tǒng)一的assertion機制,Java程序通常使用if-then-else或者switch-case語句進行assertion檢查,而且檢查的數(shù)據(jù)類型也不完全相同。assertion機制讓Java程序員用統(tǒng)一的方式處理assertion問題,而不是按自己的方式處理。另外,如果用戶使用自己的方式進行檢查,那么這些代碼在發(fā)布以后仍然將起作用,這可能會影響程序的性能。而從語言言層次支持assertion功能,這將把assertion對性能帶來的負面影響降到最小。

    Java是通過增強一個關(guān)鍵字assert實現(xiàn)支持assertion,而不是使用一個庫函數(shù)支持,這說明Java認為assertion對于語言本身來說是非常重要的。實際上,在Java的早期的規(guī)范中,Java是能夠支持assert的,但是由于一些實現(xiàn)的限制,這些特性從規(guī)范中除去了。因此,assert的再次引入應(yīng)該是恢復(fù)了Javaassert的支持。C語言就是通過Assert.h函數(shù)庫實現(xiàn)斷言的支持。

    Javaassertion的開啟也和C語言不太一樣,我們都知道在C語言中,assertion的開啟是在編譯時候決定的。當我們使用debug方式編譯程序時候,assertion被開啟,而使用release方式編譯時候,assertion自動被關(guān)閉。而Javaassertion卻是在運行的時候進行決定的。其實,這兩種方式是各有優(yōu)缺點。如果采用編譯時決定方式,開發(fā)人員將處理兩種類型的目標碼,debug版本和release版本,這加大了文檔管理的難度,但是提高了代碼的運行效率。Java采用運行時決定的方式,這樣所有的assertion信息將置于目標代碼中,同一目標代碼可以選擇不同方式運行,增強目標代碼的靈活性,但是它將犧牲因為assertion而引起一部分性能損失。Java專家小組認為,所犧牲的性能相當小,因此java采用了運行時決定方式。

    另外,我們注意到AssertionError作為Error的一個子類,而不是RuntimeException。關(guān)于這一點,專家組也進行了長期的討論。Error代表一些異常的錯誤,通常是不可以恢復(fù)的,而RuntimeException強調(diào)該錯誤在運行時才發(fā)生的特點。AssertionError通常為非常關(guān)鍵的錯誤,這些錯誤往往是不容易恢復(fù)的,而且assertion機制也不鼓勵程序員對這種錯誤進行恢復(fù)。因此,為了強調(diào)assertion的含義,Java專家小組選擇了讓AssertErrorError的子類。

    三、 Assertion與繼承

    在本節(jié),我們將考慮assertion與繼承的關(guān)系,研究assert是如何定位的。如果開啟一個子類的assertion,那么它的父類的assertion是否執(zhí)行?

    下面的例子將顯示如果一個assert語句在父類,而當它的子類調(diào)用它時,該assertfalse。我們看看在不同的情況下,該assertion是否被處理。

    class Base

    {

      public void baseMethod()

      {

        assert      false : "Assertion failed:This is base ";// 總是assertion失敗

        System.out.println("Base Method");

      }

    }

     

    class Derived

      extends Base

    {

      public void derivedMethod()

      {

        assert false: "Assertion failed:This is derive";// 總是assertion失敗

        System.out.println( "Derived Method" );

      }

     

      public static void main( String[] args )

      {

        try

        {

          Derived derived = new Derived();

     

          derived.baseMethod(  );

     

          derived.derivedMethod();

        }

        catch( AssertionError ae )

        {

          System.out.println(ae);

        }

      }

    }

    運行命令

    含義

    結(jié)果

    Java Derived

    不啟用assertion

    Base Method
    Derived Method

    Java -ea Derived

    開啟所有assertion

    Java.lang.AssertionError:Assertion Failed:This is base

    Java -da Derived

    關(guān)閉所有assertion

    Base Method
    Derived Method

    Java -ea:Base Derived

    僅打開Baseassertion

    Java.lang.AssertionError:Assertion Failed:This is base

    Java -ea:Derived Derived

    僅打開Derivedassertion

    Base Method
    Java.lang.AssertionError:Assertion Failed:This is derived

    從這個例子我們可以看出,父類的assert語句將只有在父類的assert開啟才起作用,如果僅僅開啟子類的assert,父類的assert仍然不運行。例如,我們執(zhí)行java -ea:Derived Derived的時候,Base類的assert語句并不執(zhí)行。因此,我們可以認為,assert語句不具有繼承功能。

    四、 Assertion的使用

    assertion的使用是一個復(fù)雜的問題,因為這將涉及到程序的風(fēng)格,assertion運用的目標,程序的性質(zhì)等問題。通常來說,assertion用于檢查一些關(guān)鍵的值,并且這些值對整個程序,或者局部功能的完成有很大的影響,并且這種錯誤不容易恢復(fù)的。assertion表達式應(yīng)該短小、易懂,如果需要評估復(fù)雜的表達式,應(yīng)該使用函數(shù)計算。以下是一些使用assertion的情況的例子,這些方式可以讓java程序的可靠性更高。

    1.      檢查控制流; 在if-then-elseswith-case語句中,我們可以在不應(yīng)該發(fā)生的控制支流上加上assert false語句。如果這種情況發(fā)生了,assert能夠檢查出來。
    例如:x取值只能使1,2,3,我們的程序可以如下表示

    2.      在私有函數(shù)計算前,檢查輸入?yún)?shù)是否有效;對于一私有些函數(shù),要求輸入滿足一些特定的條件,那么我們可以在函數(shù)開始處使用assert進行參數(shù)檢查。對于公共函數(shù),我們通常不使用assertion檢查,因為一般來說,公共函數(shù)必須對無效的參數(shù)進行檢查和處理。而私有函數(shù)往往是直接使用的。
    例如:某函數(shù)可能要求輸入的參數(shù)必須不為null。那么我們可以在函數(shù)的一開始加上 assert parameter1!=null : "paramerter is null in test method";

    3.      在函數(shù)計算后,檢查函數(shù)結(jié)果是否有效;對于一些計算函數(shù),函數(shù)運行完成后,某些值需要保證一定的性質(zhì),因此我們可以通過assert檢查該值。
    例如,我們有一個計算絕對值的函數(shù),那么我們就可以在函數(shù)的結(jié)果處,加上一個語句:
    assert  value>=0:"Value should be bigger than 0:"+value;
    通過這種方式,我們可以對函數(shù)計算完的結(jié)果進行檢查。

    4.      檢查程序不變量;有些程序中,存在一些不變量,在程序的運行生命周期,這些不變量的值都是不變的。這些不變量可能是一個簡單表達式,也可能是一個復(fù)雜的表達式。對于一些關(guān)鍵的不變量,我們可以通過assert進行檢查。



    Gavin

    posted on 2011-11-25 13:20 GavinMiao 閱讀(778) 評論(0)  編輯  收藏 所屬分類: corejava

    主站蜘蛛池模板: 亚洲精品人成无码中文毛片| 97久久免费视频| 三级片免费观看久久| 激情小说亚洲色图| 国内成人精品亚洲日本语音| 亚洲AV色无码乱码在线观看 | 亚洲精品在线免费观看视频| 无码国产精品一区二区免费模式 | 怡红院免费的全部视频| 久久er国产精品免费观看8| 成人免费ā片在线观看| 中文字幕一区二区免费| 午夜视频免费在线观看| 日韩在线永久免费播放| 24小时免费看片| 欧洲黑大粗无码免费| 暖暖在线日本免费中文| 全部免费毛片免费播放| 亚洲中文字幕无码爆乳av中文| 亚洲精品视频久久久| 亚洲日韩欧洲无码av夜夜摸| 亚洲AV中文无码乱人伦下载| 亚洲网址在线观看| 丁香婷婷亚洲六月综合色| 精品亚洲成a人在线观看| yellow视频免费在线观看| a级午夜毛片免费一区二区| 久久久久久国产精品免费免费男同 | 成人特级毛片69免费观看| 中文字幕a∨在线乱码免费看| 久久成人无码国产免费播放| 亚洲免费在线观看视频| 成人毛片18女人毛片免费| 免费中文字幕不卡视频| 亚洲男人的天堂www| 亚洲伊人精品综合在合线| 在线观看亚洲免费视频| a级毛片免费全部播放| 久久久高清免费视频 | 免费国产黄网站在线观看视频 | 青柠影视在线观看免费高清|