2015-04-04 97 views
5

我總是理解靜態變量在引用它們時共享一個實例。我想把這個測試結果告訴我,但結果與我預期的不同。增加一個整型變量不會影響另一個引用同一個對象的變量

static Integer counter = 0; 
static Integer test = counter; 

public static void main(String args[]) { 
    counter++; 
    System.out.println("counter: " + counter); 
    System.out.println("test: " + test); 
} 

輸出:

計數器:1

測試:0

由於test引用counter我認爲,當我遞增counter然後test將自動以及遞增。但是,看起來test從某處引用0,問題在哪裏?

+0

它們都是基元而不是對象。 'test'最初是'0',如果你想增加測試,你需要調用'test ++'。 – 2015-04-04 23:18:23

回答

4

由於test引用counter

這個假設是錯誤的。在Java中,你不能引用變量。存儲在變量中的是一個值。該值可以是原始類型值或參考類型值。在基元的情況下,該值是基元的值。在引用類型的情況下,

The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object.

int a = 0; 
int b = a; 

可變a進行評估,以產生一個值,0,並將該值存儲在b

Integer a = 0; 
Integer b = a; 

0通過Integer.valueOf(int)並將該值轉化爲Integer,到Integer對象的引用存儲在a。然後對a進行評估,產生對Integer對象的引用的值,並將該值存儲在b中。

這是

還討論相同的概念,事實的變量是static是無關緊要的。

解決這個問題的唯一辦法是更新test手動即

counter++; 
test = counter; 
+0

是否有一個JLS引用說明了將盒裝類型明確分配給其他盒裝類型的轉換?我環顧四周,找不到它。 – merlin2011 2015-04-04 23:31:47

+1

@ merlin2011你的意思是[拳擊轉換](http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.7)? – 2015-04-04 23:32:28

+0

只談''整數''整數'和'整數'談'整型'後的部分。在這裏,我們將'Integer'看作'Integer'直接賦值,這是我無法找到的參考。 – merlin2011 2015-04-04 23:33:25

1

test不參考counter。它具有相同的初始值int是一個原始的。

0

test不是指針到counter:要設置其值等於初始計數器,但之後counter任何更改都不會在test的值中反映出來。

如果你想有兩個引用到相同的可變值,你可以使用像AtomicInteger

static AtomicInteger counter = new AtomicInteger(0); 
static AtomicInteger test = counter; 
public static void main(String args[]) { 
    counter.incrementAndGet(); 
    System.out.println("counter: " + counter); 
    System.out.println("test: " + test); 
} 

輸出:

counter: 1 
test: 1 
+0

因爲不符合規格。 – 2015-04-04 23:20:57

-2

你需要一個原始和引用的區分-目的。整數不是原始的「本質」,但由於'boxing',它們具有特殊屬性。你有什麼是一個原始的intValue()因此它得到的初始值(它沒有更多的關係到計數器)。

呃...對於記錄的「降級」:OP已將其字段從「int」更改爲「Integers」,因此我的初始答案不正確。

2

這是我的理解。

  • 第1步:當你說Integer counter = 0;你實際上做的是
    Integer counter = new Integer(0); 在這裏你創建了一個Integer object,其值在0和counter被reffering它。
  • 步驟2:Integer test = counter;

    現在test也指的是同一Integer object我們 在步驟1

  • 步驟3中創建:這裏談到的棘手的部分。當您在主要方法中使用counter++;時,Java 自動裝箱自動拆箱 功能正在爲您實現下面的代碼。

    counter = Integer.valueOf(counter.intValue() + 1);

作爲Integer類是在Java中,當該值被遞增從0到1 不可改變,所述valueOf()方法是創建一個新Integer object並在它存儲代替的新值1更改舊對象的值(請參閱下面的Java的valueOf()方法實現)。當您使用counter引用新對象時,它將取消引用舊值爲Integer object的值爲0的值。但參考變量test仍舊保留舊Integer object。這就是test打印舊值的原因。

Java的的valueOf()從庫Integer類方法

638  public static Integer More ...valueOf(int i) { 
639   assert IntegerCache.high >= 127; 
640   if (i >= IntegerCache.low && i <= IntegerCache.high) 
641    return IntegerCache.cache[i + (-IntegerCache.low)]; 
642   return new Integer(i); //See, new object is created here. 
643  } 

請參閱以下詳細圖解說明。

實線意味着引用變量仍然持有對象。

虛線暗示參考變量不再是持有對象。

enter image description here