2010-06-25 56 views
1

我正在用java編寫一些東西,最近我遇到了一些問題。簡而言之,我需要將我創建的對象與之前用不同數據實例化的這個非常類的另一個實例進行比較。在Java中傳遞對象引用的問題

看起來是這樣的:

a newA = null; 
a oldA = null; 

while(someBreakCondition) { 
    newA = new a(); 

    newA.x = getSomeValue(); 

    // now i want to compare the two objects 
    if(oldA != null) { 
     if(newA.time != oldA.time) { 
      // ... 
     } 
    } 

    // now my newA gets to be my oldA, since in the next iteration, a new newA is created 
    oldA = newA; 
} 

用類:

class a { 
    public long time; 
    public int x; 

    public a() { 
     time = System.currentTimeMillis; 
    } 
} 

的問題是,我最終找到了從紐瓦的值總是等於那些從oldA。所以我想......在循環的最後一行傳遞對象的引用出錯了...... 我認爲java總是傳遞對象的引用,除非顯式複製()被調用?

如果這確有影響:此代碼運行在Android上 - 不知道是否Dalvik虛擬機混亂與此aroung ...

+5

由:http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html特別是nr。 9,命名約定 – wds 2010-06-25 07:59:07

+0

「我最終發現newA的值總是等於那些來自oldA的值」 - 「I end up」的意思是「在'while循環」的末尾嗎?因爲在這種情況下,答案是微不足道的。 :s – 2010-06-25 08:38:30

回答

7

我想你可能確實有兩個不同的對象,但他們都具有相同的值time。目前的millis並不十分精確地區分快速連續構建的兩個對象,除非內部循環長時間運行。即使是Mhz處理器也會以微秒爲單位來測量迭代,而不是毫秒。

+0

+1注意:只有在兩個時間不同的情況下才會運行內部循環,所以至少在第一個毫秒內,如果內部循環長時間運行,則不會產生影響。 – 2010-06-25 09:02:52

+0

啊對,很好。所以代碼基本上是在毫秒之前構造至少幾千個對象。 – wds 2010-06-25 09:03:52

4

有一個機會,兩個a對象在同一毫秒內創建,所以'時間'字段是相等的。

我不知道你比較的要求,但也許你應該覆蓋equals

public class A { 
    private long time; 
    private int x; 

    public A() { 
    time = System.currentTimeInMillis(); 
    } 

    public void setX(int x) { 
    this.x = x; 
    } 

    public int getX() { 
    return x; 
    } 


    public boolean equals(Object other) { 
    if (!(other instanceof A)) return false; 

    // two A instances are equal if they are created 
    // within the same millisecond 
    return ((A) other).time == time); 
    } 
} 

然後就做了

if (!(newA.equals(oldA)) { 
    // ... 
} 

對於未來的編碼 - 讓他們開始請寫明類用大寫字母(編碼約定)

0

在你的循環的最後一行你寫oldA=newA 這使得oldA和newA共享相同的參考。因此,當您更改newA的值newA=new a()時,oldA的值也會發生變化(因此您將擁有oldA.x == newA.x)。

編輯:我做了一些測試,發現我說的是完全錯誤的,對此感到抱歉。然而,氙礦給出的代碼工作正常。滿足條件newA.time != oldA.time

+5

不!沒有!沒有!這是絕對不正確的! 'oldA'存儲對'a'實例的引用,當將'a'的新實例賦給'newA'時,這個引用永遠不會改變。 – 2010-06-25 08:19:08

+1

安德烈亞斯是對的。你可以把'oldA'和'newA'看作兩個指針。 'oldA' ='newA'使它們都指向同一個對象。當你執行'newA = new A()'時,你使'newA'指向一個不同的(一個新的)對象。這對'oldA'沒有任何影響。 – wds 2010-06-25 08:27:57

+0

-1錯誤。如果'oldA = newA;',是的,它們會指向同一個對象,但是'newA = new a();'**不會修改'oldA'引用的對象。它所做的就是創建一個'a'的新實例並將引用存儲在'newA'中,以便'oldA'和'newA'引用不同的對象 – chrisbunney 2010-06-25 08:41:11

1

我不知道如何把代碼放到註釋,所以我要添加該爲Aymen的答案迴應這是錯誤的:)

試試這個,你會看到什麼回事:)

public class Test { 
    private int value; 
    public Test(){ 

    } 

    public int getValue() { 
    return value; 
    } 

    public void setValue(int value) { 
    this.value = value; 
    } 


} 

public class Main { 

    public static void main(String[] args) { 
     Test oldA = null; 
     Test newA = null; 


     newA = new Test(); 
     newA.setValue(1); 

     oldA = newA; 

     // both variables references the same object: output: 1 - 1 
     System.out.println("newA: " + newA.getValue()); 
     System.out.println("oldA: " + oldA.getValue()); 

     newA = new Test(); 
     newA.setValue(2); 

     // now we have different objects: output: 2 - 1 
     System.out.println("newA: " + newA.getValue()); 
     System.out.println("oldA: " + oldA.getValue()); 

    } 

} 
1

通過「我結束了」,你的意思是「後,我走出while循環」?

因爲在這種情況下,問題很簡單:在上一次循環迭代中,oldA被newA的最後一個值覆蓋,而newA不會被新的a實例覆蓋。

因此,當您退出while循環時,newA和oldA始終相等 - 最後一次循環執行的最後一個歸因步驟的結果。