[教學] Assertion 介紹與使用
Assertion 是新版 SCJP 考題增加的項目,這東西其實跟 Exception 有點相似
然而它是屬於 java.lang.Error 的東西
我只是介紹他在程式碼中的使用方法
而編譯的使用方法可以先參照下面網址的簡介
http://www.oreilly.com.tw/sleepless/shithappen2.htm
原始來源是來自於下面 sun 的文件 Programming With Assertions
http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html
一、 assert的兩種語法:
assert Expression1;
Expression1 必須是個 boolean Expression
當 Expression1 為 false 時,會丟出個 AssertionError
assert Expression1 : Expression2;
Expression1 是 boolean Expression
Expression2 則是一個值
當 Expression1 為 false 時,會把 Expression2 的值傳給 AssertionError 的建構子
二、 把 Assertion 放入程式碼
這裡分成三個 section
˙Internal Invariants
˙Control-Flow Invariants
˙Preconditions, Postconditions, and Class Invariants
但是先有兩個 Assertion 不能使用的重點:
1.Do not use assertions for argument checking in public methods.
意思是請不要把 Assertion 跟 Exception 弄混了,兩者做的事是不同的
2.Do not use assertions to do any work that your application requires for
correct operation.
ex:
這是錯的:
// Broken! - action is contained in assertion
assert names.remove(null);
要改成:
// Fixed - action precedes assertion
boolean nullsRemoved = names.remove(null);
assert nullsRemoved; // Runs whether or not asserts are enabled
原因似乎是 assertion 預設是 disable,要寫的明確點他才能用...
˙Internal Invariants
☆use an assertion whenever you would have written a comment that asserts an
invariant.
ex1:
原式:
if (i % 3 == 0) {
...
} else if (i % 3 == 1) {
...
} else { // We know (i % 3 == 2)
...
}
後式:
if (i % 3 == 0) {
...
} else if (i % 3 == 1) {
...
} else {
assert i % 3 == 2 : i;
...
}
意思是你原本註解為你已知的事實,可以用 assert 來確保不會錯
ex2:
原式:
switch(suit) {
case Suit.CLUBS:
...
break;
case Suit.DIAMONDS:
...
break;
case Suit.HEARTS:
...
break;
case Suit.SPADES:
...
}
你通常會在 switch 裡加個 default,這裡就可以用到 assertion
default:
assert false : suit;
或是另一種像是丟出 Exception 的語法
default:
throw new AssertionError(suit);
這會強制丟出個 AssertionError
˙Control-Flow Invariants
☆place an assertion at any location you assume will not be reached.
語法: assert false;
ex:
原式:
void foo() {
for (...) {
if (...)
return;
}
// Execution should never reach this point!!!
}
後式:
void foo() {
for (...) {
if (...)
return;
}
assert false; // Execution should never reach this point!
}
就是在你程式執行不到的地方加 assertion
˙Preconditions, Postconditions, and Class Invariants
這裡分成:
˙Preconditions
└˙Lock-Status Preconditions
˙Postconditions
˙Class invariants
Preconditions — what must be true when a method is invoked.
☆Do not use assertions to check the parameters of a public method.
ex:
原式:
public void setRefreshRate(int rate) {
// Enforce specified precondition in public method
if (rate <= 0 || rate > MAX_REFRESH_RATE)
throw new IllegalArgumentException("Illegal rate: " + rate);
setRefreshInterval(1000/rate);
}
後式:
private void setRefreshInterval(int interval) {
// Confirm adherence to precondition in nonpublic method
assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;
... // Set the refresh interval
}
意思是這狀況下 assertion 只能出現在 nonpublic 裡
請記得這是個 Error,而不是 Exception
Lock-Status Preconditions — preconditions concerning whether or not a given
lock is held.
ex:
原式:
private Object[] a;
public synchronized int find(Object key) {
return find(key, a, 0, a.length);
}
// Recursive helper method - always called with a lock on this object
private int find(Object key, Object[] arr, int start, int len) {
...
}
後式:
// Recursive helper method - always called with a lock on this.
private int find(Object key, Object[] arr, int start, int len) {
assert Thread.holdsLock(this); // lock-status assertion
...
}
意思是可以用 assertion 來檢查有沒有 lock
Postconditions — what must be true after a method completes successfully.
這種狀況可以分別用在 public 與 nonpublic 裡
public:
ex:
public BigInteger modInverse(BigInteger m) {
if (m.signum <= 0)
throw new ArithmeticException("Modulus not positive: " + m);
... // Do the computation
assert this.multiply(result).mod(m).equals(ONE) : this;
return result;
}
nonpublic:
ex:
原式:
void foo(int[] array) {
// Manipulate array
...
// At this point, array will contain exactly the ints that it did
// prior to manipulation, in the same order.
}
後式:
void foo(final int[] array) {
// Inner class that saves state and performs final consistency check
class DataCopy {
private int[] arrayCopy;
DataCopy() { arrayCopy = (int[]) array.clone(); }
boolean isConsistent() { return Arrays.equals(array, arrayCopy); }
}
DataCopy copy = null;
// Always succeeds; has side effect of saving a copy of array
assert ((copy = new DataCopy()) != null);
... // Manipulate array
// Ensure array has same ints in same order as before manipulation.
assert copy.isConsistent();
}
使用 inner class 跟這兩個 assertion 可以用來確認你的資料
Class invariants — what must be true about each instance of a class.
ex:
// Returns true if this tree is properly balanced
private boolean balanced() {
...
}
在這 ex 中,加入
assert balanced();
是為了確認這個 class 裡的 instance
後記:
為了參加 SCJP,這個 Assertion 讓我去找了些資料
但是市面上有許多標示 1.4 版的書,根本就沒有提到
所以資料幾乎都是英文的
像是 O'REILLY 原文新出的 Learning Java, 2nd Edition
http://www.oreilly.com/catalog/learnjava2/
裡面就有介紹了,可惜天瓏好像還沒進貨 @.@"
下面是幾個我覺得不錯的 assertion 介紹
http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html
http://www.javaworld.com/javaworld/jw-11-2001/jw-1109-assert.html
http://www.jcp.org/content/main/jsr/detail/materials/asrt_prop.html
第一個就是我這篇的來源
我只作了非常精簡的介紹,想要瞭解更詳細的話,就去看看原本的文章跟API吧
其實我之前對這 assertion 根本沒聽過...
想說沒有 Exception 跟 Assertion 還是一樣可以活的很快樂...
也不知道怎麼去測他就是...
希望能有前輩給我們更清楚的說明
也希望想參加新版 SCJP 考試的人能夠來一起研究囉~ ^o^"
--
歡迎加入◢██◣◢██◣█◣ ◣◢██◣☆swanky
██ ██◤███ ███◤█
██ ████◥█◢◤████
◥█◤ ◥█◥◤ ◥◤ ◥█◥◤版的討論
--
※Post by swanky from u138-246.u61-70.giga.net
▁▃▅▆▄▃▁ ▃▅▂ ▁ ▁▃▄▁
▃▅歡迎大家到市立師院▄ 凱達格蘭▆▅▄▇ _▁▃▄▅█▅▄▂▁_▄▃
▇▅▄ ▄▅ ccbbs.tmtc.edu.tw ▂▃▆▇▆▁▂▄▆▆▇████▆▃
java 近期熱門文章
PTT數位生活區 即時熱門文章