1. 程式人生 > >【碼農每日一題】Java 自增自減運算子神坑筆試題

【碼農每日一題】Java 自增自減運算子神坑筆試題

問:下面程式的執行結果是什麼?

  1. int count =0;

  2. for(int i=0; i<100; i++){

  3.    count = count++;

  4. }

  5. System.out.println("count="+ count);

答:執行結果是 count = 0。

首先 count++ 是一個有返回值的表示式,返回值是 count 自加前的值,Java 對自加處理的流程是先把 count 的值(不是引用)拷貝到一個臨時變數區,然後對 count 變數加1,接著返回臨時變數區的值。

所以上面程式碼塊中第一次迴圈的執行步驟是 JVM 把 count 值(0)拷貝到臨時變數區,然後 count 值加 1,這時 count 的值是 1,接著返回臨時變數區的值(值是 0),最後返回值賦值給 count,此時 count 值被重置成 0;所以上面程式碼語句 count = count++; 可以按照如下程式碼來理解:

  1. int autoAdd(int count){

  2. int temp = count;

  3.    count = count +1;

  4. return temp;

  5. }

所以第一次迴圈後 count 的值還是 0,其他 99 次的迴圈也是一樣的,最終導致 count 的值始終沒有改變,仍然保持著最初的狀態;如果想要列印結果為 100 則需要修改 count = count++; 語句為 count++; 即可。因此對於 ++/-- 運算在 java 中一定要警惕這個陷阱(-- 運算子也一樣存在這個問題),不過這個問題在不同的語言環境中的實現是不同的,在 C++ 中 count = count++; 與 count++ 是等效的,而在 java 等語言中 count = count++; 與 count++ 是不等效的,區別如這道題。

問:Java 或者 Android 開發中可以通過哪些方式來保證併發安全的自增自減操作?

答:java 預設的自增自減運算子是非併發安全的,要想實現併發安全的自增自減操作可以通過如下幾種方式實現。

通過 synchronized 程式碼塊或者方法來保證自增自減併發安全。

通過主動使用 Lock 鎖來保證自增自減併發安全。

通過 JDK 提供的 AtomicInteger 類來直接保證自增自減併發安全。

上面幾種做法中最推薦直接使用 AtomicInteger 的方式,因為其相對於其他幾種方式封裝性非常便捷,此外其實現基於 volatile 物件的 CAS 操作來保證併發安全,算是一種相對高效的方式。