首頁 Java java教程 Java陷阱之assert關鍵字詳解

Java陷阱之assert關鍵字詳解

Jan 16, 2017 pm 04:04 PM

一、概述
 
在C和C++語言中都有assert關鍵,表示斷言。
在Java中,同樣也有assert關鍵字,表示斷言,用法和意義都差不多。

二、語法
 
在Java中,assert關鍵字是從JAVA SE 1.4 引入的,為了避免和舊版本的Java代碼中使用了assert關鍵字導致錯誤,Java在執行的時候默認是不啟動檢查斷言的(這個時候,所有的斷言語句都將忽略!),如果要開啟斷言檢查,則需要用開關-enableassertions或-ea來開啟。

assert關鍵字語法很簡單,有兩種用法:

1、assert
如果為true,則程式繼續執行。
如果為false,則程式拋出AssertionError,並終止執行。

2、assert :
如果為true,則程式繼續執行。
如果為false,則程式拋出java.lang.AssertionError,並輸入。

三、應用實例
 
下面給出一個例子,以例子說明其用法:

public class AssertFoo {
    public static void main(String args[]) {
        //断言1结果为true,则继续往下执行
        assert true;
        System.out.println("断言1没有问题,Go!");

        System.out.println("\n-----------------\n");

        //断言2结果为false,程序终止
        assert false : "断言失败,此表达式的信息将会在抛出异常的时候输出!";
        System.out.println("断言2没有问题,Go!");
    }
}
登入後複製

將程式儲存程式碼到C:AssertFoo.java,然後按照下面的方式執行,查看控制台輸出結果:

1、編譯程式:
C:>javac AssertFoo.java

2、預設執行程序,沒有開啟- ea開關:
C:>java AssertFoo
斷言1沒問題,Go!

-----------------

斷言2沒有問題,Go!

3、開啟-ea開關,執行程式:
C:>java -ea AssertFoo
斷言1沒有問題,Go!

-----------------

Exception in thread "main" java.lang.AssertionError: 斷言失敗,此表達式的資訊將
會在拋出異常的時候輸出!
        at AssertFoo.main(AssertFoo.java:10)

四、陷阱
 
assert關鍵字用法簡單,但是使用assert往往會讓你陷入越來越深的陷阱中。應避免使用。筆者經過研究,總結了以下原因:

1、assert關鍵字需要在運行時候明確開啟才能生效,否則你的斷言就沒有任何意義。而現在主流的Java IDE工具預設都沒有開啟-ea斷言檢查功能。這就代表你如果使用IDE工具編碼,調試運行時候會有一定的麻煩。而且,對於Java Web應用,程式碼都是部署在容器裡面,你沒辦法直接去控製程式的運行,如果一定要開啟-ea的開關,則需要更改Web容器的運行設定參數。這對程序的移 植和部署都帶來很大的不便。

2、用assert代替if是陷阱之二。 assert的判斷和if語句差不多,但兩者的作用有著本質的區別:assert關鍵字本來是為測試調試程序時使用的,但如果不小心用assert來控制了程序的業務流程,那在測試調試結束後去掉assert關鍵字就意味著修改了程式的正常的邏輯。

3、assert斷言失敗將面臨程序的退出。這在一個生產環境下的應用是絕對不能容忍的。一般都是透過異常處理來解決程式中潛在的錯誤。但是使用斷言就很危險,一旦失敗系統就掛了。

 
五、對assert的思考
 
assert既然是為了調試測試程序用,不在正式生產環境下用,那應該考慮更好的測試JUint來代替其做用,JUint相對assert關鍵的所提供的功能是有過之而無不及。當然完全可以透過IDE debug來進行調試測試。在此看來,assert的前途一片昏暗。

因此,應避免在Java中使用assert關鍵字,除非哪一天Java預設支援開啟-ea的開關,這時候可以考慮。對比一下,assert能為你帶來多少好處,多少麻煩,這是我們選擇是否使用的原則。

================================================ ============
comment:
反過來說,在某些開源元件中,例如validator、junit中,判斷過程彷彿使用了斷言風格,很有可能使用了大量的斷言,但筆者在沒看源碼之前不能確定。
如果是開發階段的簡單測試,junit就是一個便捷強悍的工具,沒有理由自己寫斷言而不去用它。

================================================ ============
comment:
首先可以用在單元測試程式碼中。 junit侵入性是很強的,如果整個工程大量的程式碼都使用了junit,就難以去掉或是選擇另一個框架。如果單元測試程式碼 很多,並且想重複使用這些單元測試案例,應該選擇assert而不是junit,以便使用別的單元測試框架,例如TestNG。同理正式的功能代碼根本就不應 該出現Junit,應該使用assert.

assert主要適合在基類,框架類,接口類,核心代碼類,工具類中。換言之,當你的程式碼的呼叫者是另一個程式設計師寫得業務代碼,或是另外一個子系統時,就很有必要使用它。例如你做了一個快速排序的演算法

public static List<int> quickSort(List<int> list){
  assert list != null;
  // 申请临时空间
  //开始排序
  for(int i : list){
      //
  }
}
登入後複製

這種情況下,如果不檢查傳入參數的正確性,會拋出一個莫名其妙的空指標錯誤。你的呼叫者可能不清楚你程式碼的細節,在一個系統的深處調試一個空指標錯誤是很浪費時間的。就應該直接明確的告訴你的呼叫者是傳入的參數有問題。否則他會懷疑你的程式碼有BUG。使用assert可以避免兩個程式設計師之間互相指責對方寫的程式碼有問題。


assert適用那些你知道具體是什麼錯誤,你和你的呼叫者已經約定應該由你的呼叫者去排除或檢查的錯誤。你透過一個斷言告訴你的呼叫者。 assert不適用那些外部系統造成的錯誤,例如使用者輸入資料的錯誤,某個外部檔案格式錯誤。這些錯誤不是你的呼叫者而是使用者造成的,甚至不屬於異常,因為出現輸入錯誤和檔案格式錯誤是經常的,這些錯誤應該由業務代碼去檢查。

assert比較適合被頻繁調用的 基類,框架代碼,工具類,核心代碼,接口代碼中,這正是它在運行時被去掉的原因。測試程式碼應該在測試階段開啟-ea參數,以便對系統深處的核心程式碼做仔細的測試。

Java較少使用assert的原因是Java有很完整的OO體系,強制類型轉換出現得較少,所以不需要類似c那樣需要頻繁的檢查指針的類型是否正確,指針是否為空。同時Java也很少直接管理記憶體或緩衝區,所以不需要頻繁的檢查傳入的緩衝區是否為空或已經越界。

但使用好assert有助於提高框架程式碼的正確性和減少框架程式碼的使用者的偵錯時間。

================================================ ===============
comment:
assert要達到的目的是讓程式設計師方便的發現自己的邏輯錯誤,並且不影響程式的效率。 assert所發現的錯誤,是完全不該出現的,是不能用異常取代的。異常,那是系統所允許的,或者是系統不可控的“錯誤”,它不是程式設計師的邏輯問題。

assert應該是開發階段打開,而在發布後關閉。

更多Java陷阱之assert關鍵字詳解相關文章請關注PHP中文網!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1672
14
CakePHP 教程
1428
52
Laravel 教程
1332
25
PHP教程
1277
29
C# 教程
1257
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

See all articles