<span style="font-size:18px;">class Creature {
private static long numCreated = 0;
public Creature() {
numCreated++;
}
public static long numCreated() {
return numCreated;
}
}
public class Creator {
public static void main(String[] args) {
for (int i = 0; i < 100; i++)
Creature Creature = new Creature();
System.out.println(Creature.numCreated());
}
}</span>
本地變量聲明問題小結:
(1)上面的Java代碼看起來似乎應該列印100,但是實際上它什麼也沒有列印!
(2)通過Javac編譯可以發現一些錯誤的診斷資訊,但對于解決問題作用不大。
問題剖析:
1、Java語言規範不允許一個本地變量聲明語句在for、while或do循環中重複執行。
2、一個本地變量聲明作為一條語句隻能直接出現在一個語句塊中。
3、一個語句塊是由一對花括号以及包含這對花括号中的語句和聲明構成的。
解決方法:
1、将Creature creature = new Creature 這個聲明置于語句塊中。
2、将該聲明用一個無任何修飾的構造器調用(new Creature)來替代将更有實際意義,這樣強調對新建立對象的引用正在被丢棄。
再問題抛出:
1、用于跟蹤Creature執行個體個數的變量(numCreated)是long類型而不是int類型。原因是:我們很容易想到,一個城程式建立出的某個執行個體可能多于int數值的最大值,但是它不會多于long數值的最大值。int數值最大值為2^31-1,long數值的最大值為2^63-1.
溫馨提醒:
1、題目中建立的計數政策并不是線程安全的。如果多個線程可以并行地建立對象,那麼遞增計數器的代碼和讀取計數器的代碼都應該被同步。(synchronized)
2、代碼塊的改寫如下所示:
class Creature {
private static long numCreated = 0;
public Creature() {
synchronized (Creature.class){
numCreated++;
}
}
public static synchronized long numCreated() {
return numCreated;
}
}
3、另外,如果使用的是5.0或者更新的版本,可以使用一個AtomicLong執行個體,它在面臨并發時可以繞過對同步的需求。
4、代碼事例:
import java.util.concurrent.atomic.AtomicLong;
public class Creature {
private static AtomicLong numCreated = new AtomicLong();
public Creature(){
numCreated.incrementAndGet();
}
public static long numCreated(){
return numCreated.get();
}
}
總結:
(1)一個本地變量聲明不能被用作for、while、do循環中重複執行語句,它作為一條語句隻能出現在一個語句塊彙總。
(2)在使用一個變量來對執行個體的建立進行計數時,要使用long類型而不是int類型的變量,以防止溢出!