2008-09-05 55 views
8

如何將10乘以Integer對象並找回Integer對象?如何將10乘以Java中的「Integer」對象?

我正在尋找這樣做的最好方法。

我可能會這樣做: 從Integer獲取int對象,將其與另一個int相乘,並用此int值創建另一個Integer對象。

代碼將是這樣......

integerObj = new Integer(integerObj.intValue() * 10); 

但是,我看到這裏筆者是做什麼的這樣一個代碼:從Integer對象獲取String,並置「0」,在結束然後得到Integer對象返回使用Integer.parseInt

的代碼是這樣的:

String s = integerObj + "0"; 
integerObj = Integer.parseInt(s); 

的是無論以哪種方式做任何優點?

在這種情況下,一般情況下最有效/最新的方法是什麼?

+0

我還建議你檢查一下使用Integer是否真的需要。 Joshua指出在有效Java中使用原語要快很多倍。所以,如果可以的話,堅持** int **。 – 2008-09-05 15:54:56

+0

使用Integer實際上是一個設計約束。這個想法是我得到一個Integer對象,我必須更新它。所以,不能取消:) – Jagmal 2008-09-05 17:40:24

+0

更新現有的Integer對象不會發生沒有反射巫術。 (像其他原始包裝類型一樣,Integer是不可變的。)你可以合理地做的最好的 - 以及任何理智的例子將會做的 - 用另一個對象代替它。對於大多數情況來說這足夠好,但是意味着`void modifyInteger(Integer i)`不會做任何有價值的事情。 – cHao 2014-04-15 02:48:58

回答

25

使用Java 5的autoboxing,你可以簡單地做:

Integer a = new Integer(2); // or even just Integer a = 2; 
a *= 10; 
System.out.println(a); 
7

字符串的方法是有趣的,但幾乎肯定是一個不好的方法來做到這一點。

獲取Integer的int值並創建一個新值將非常快,其中parseInt的調用相當昂貴。

總的來說,我跟你原來的方法(正如其他人所指出的,可沒有這麼多的混亂,如果你已經自動裝箱爲Java 5中引入完成)同意。

1

請從第二種方法了,最好的辦法是,如果你使用的是Java 1.5的自動裝箱,什麼前面你的第一個例子是最好的。

1

使用String方法的解決方案由於各種原因不太好。有些是美學原因,其他人是實用的。

實際上,更多的對象是通過String版本創建的,而不是更常規的形式(如您在第一個示例中所表達的)。

上的美學筆記,我認爲第二個版本掩蓋了代碼的意圖,這是幾乎得到它產生你想要的結果一樣重要。

3

與第二方式的問題是字符串在Java中的處理方式:

  • "0"在編譯時被轉換成一個恆定字符串對象。
  • 每次調用此代碼時,s都被構造爲一個新的String對象,而javac將該代碼轉換爲String s = new StringBuilder().append(integerObj.toString()).append("0").toString()(舊版本的StringBuffer)。即使您使用相同的integerObj,即,

    String s1 = integerObj + "0"; String s2 = integerObj + "0";

    (s1 == s2)false,而s1.equals(s2)true

  • Integer.parseInt無論如何,內部電話new Integer(),因爲Integer是不可變的。

順便說一下,自動裝箱/拆箱在內部與第一種方法相同。

0

上面的工具包的答案是正確的,也是最好的方法,但它並沒有給出正在發生的事情的完整解釋。 假設Java 5或更高版本:

Integer a = new Integer(2); // or even just Integer a = 2; 
a *= 10; 
System.out.println(a); // will output 20 

你需要知道的是,這是完全一樣的做:

Integer a = new Integer(2); // or even just Integer a = 2; 
a = a.intValue() * 10; 
System.out.println(a.intValue()); // will output 20 

通過在對象上執行操作(在這種情況下,* =) 'a',你不會改變'a'對象中的int值,但實際上將一個新對象分配給'a'。 這是因爲'a'爲了執行乘法而自動取消裝箱,然後乘法的結果被自動裝箱並分配給'a'。

整數是一個不可變的對象。 (所有的包裝類是不可變的。)

採取例如這段代碼:

static void test() { 
    Integer i = new Integer(10); 
    System.out.println("StartingMemory: " + System.identityHashCode(i)); 
    changeInteger(i); 
    System.out.println("Step1: " + i); 
    changeInteger(++i); 
    System.out.println("Step2: " + i.intValue()); 
    System.out.println("MiddleMemory: " + System.identityHashCode(i)); 
} 

static void changeInteger(Integer i) { 
    System.out.println("ChangeStartMemory: " + System.identityHashCode(i)); 
    System.out.println("ChangeStartValue: " + i); 
    i++; 
    System.out.println("ChangeEnd: " + i); 
    System.out.println("ChangeEndMemory: " + System.identityHashCode(i)); 
} 

的輸出將是:

StartingMemory: 1373539035 
ChangeStartMemory: 1373539035 
ChangeStartValue: 10 
ChangeEnd: 11 
ChangeEndMemory: 190331520 
Step1: 10 
ChangeStartMemory: 190331520 
ChangeStartValue: 11 
ChangeEnd: 12 
ChangeEndMemory: 1298706257 
Step2: 11 
MiddleMemory: 190331520 

可以看到的存儲器地址爲「i」是改變(你的內存地址將會不同)。

現在讓我們做反射一個小測試,添加這個到test()方法的末尾:

System.out.println("MiddleMemory: " + System.identityHashCode(i)); 
try { 
    final Field f = i.getClass().getDeclaredField("value"); 
    f.setAccessible(true); 
    f.setInt(i, 15); 
    System.out.println("Step3: " + i.intValue()); 
    System.out.println("EndingMemory: " + System.identityHashCode(i)); 
} catch (final Exception e) { 
    e.printStackTrace(); 
} 

額外的輸出將是:

MiddleMemory: 190331520 
Step2: 15 
MiddleMemory: 190331520 

你可以看到, 「我」的內存地址沒有改變,即使我們使用反射改變了它的值。
(請不要在實際生活中使用這種反射方式!)

相關問題