2016-03-13 56 views
5

我不習慣將原始物體數據類型投射到物體上。看到了一些這樣的代碼:正在投射原始物體vs創建原始物體

public static int CompareAges(Person p1, Person p2) { 
    Integer age1 = p1.getAge(); 
    return age1.compareTo(p2.getAge()); 
} 

age1實例化顯得多餘,所以我試圖寫的代碼爲:

public static int CompareAges(Person p1, Person p2) { 
    return p1.getAge().compareTo(p2.getAge()); 
} 

但是,這提出了一個編譯器錯誤,因爲p1.getAge()是一個原始數據類型int和而不是Integer,這是一個對象。

直觀地說,我所做的:

public static int CompareAges(Person p1, Person p2) { 
    return ((Integer) p1.getAge()).compareTo(p2.getAge()); 
} 

和它的工作!

問題:我錯過了什麼?自從我們什麼時候開始將鑄造原型作爲值類型

+0

由於賦值的轉換,'int'被拆箱到'Integer'對象中。 – Tunaki

+0

@Tunaki:你的意思是裝盒?那麼,當我們嘗試投射一個整數時,編譯器推斷我們想要框起來? – displayName

+1

@displayName是的,將一個'int'強制轉換爲一個'Integer'將原語裝入Object中。 – Tunaki

回答

6

這就是內部發生:

1. Integer age1 = p1.getAge(); 
     Integer != int 
     Integer = Integer.valueOf(int) 
    Integer age1 = Integer.valueOf(p1.getAge()); 

2. p1.getAge().compareTo(p2.getAge()); 
     int.compareTo(int) 
     ^^^ 
     // it's just a primitive type, as a result - the compile error 

3. ((Integer) p1.getAge()).compareTo(p2.getAge()) 
     Integer.compareTo(int) 
     Integer.compareTo(Integer.valueOf(int)) 
    ((Integer) p1.getAge()).compareTo(Integer.valueOf(p2.getAge())) 

4. (Integer) p1.getAge() ---> Integer.valueOf(p1.getAge()) 
     // why so? look at callOfCode's answer 

但是,在我看來,((Integer) p1.getAge()).compareTo(p2.getAge())相貌醜陋。

我將它替換到

p1.getAge() > p2.getAge() ? 1 : (p1.getAge() < p2.getAge() ? -1 : 0) 

Integer.compare(p1.getAge(), p2.getAge()) // java 7+ 

我不喜歡做的事在這種情況下鑄造。


更多關於 「自動裝箱/拆箱」,你可能會發現here

+0

重溫您的答案,我發現我們可以簡單地返回'p1.getAge() - p2.getAge()'。不需要在'p1.getAge()> p2.getAge()中進行的所有比較? 1:(p1.getAge() displayName

3

Each primitive has its own boxing type

enter image description here

就像你在你的代碼做了拳擊可以是隱式(自動裝箱)或明確。

p2.getAge()是AutoBoxing或Implicit Boxing的示例。方法compareTo需要一個Object。由於它是一個基元,Java將它自動轉換爲對應的Boxing Object(整數)。你做了明確的拳擊與投(Integer) p1.getAge()

+1

@YassinHajaj:沒有隱含的拳擊真的發生。我首先嚐試了第二個代碼片段,但是這引發了編譯器錯誤。這就是爲什麼我去了第三個代碼片段,因此這個問題。 – displayName

+0

@displayName'p2.getAge()'是一個AutoBoxing或Implicit Boxing的例子。 'compareTo'方法需要一個對象。由於它是一個基元,Java將它自動轉換爲對應的Boxing Object(整數)。你做了明確的拳擊與演員 –

+1

@YassinHajaj:這就是我說的......隱含的拳擊沒有發生!引發了編譯器錯誤。 – displayName

3

new Integer(primitive);Integer integer = (Integer)primitive;之間的區別僅在字節碼級別上。在第一種情況下,Integer類的新對象在內存中創建。在第二種情況下,Integer.valueOf(primitive)在內部被調用。這是一種靜態方法,用於檢查基元是否落入-128至127的範圍內,如果下降,則返回整數緩存中的值,並且不會創建新對象。如果它不在該範圍內,則新的Integer對象被實例化。它用於提高效率。但是這樣的效率在今天是不顯着的。

int z = 1; 
Integer a = (Integer)z; 
Integer b = (Integer)z; 
//Prints true, since Integer object is retrieved from cache (range of -128 to 127) 
System.out.println(a == b); 

int w = 999; 
Integer c = (Integer)w; 
Integer d = (Integer)w; 
//Prints false, since 999 is not in cache, new Integer objects are instantiated and they points to different places in memory 
System.out.println(c == d); 
+0

我不太明白-128到127的事情。你是否表示在演員演出時你不會總是獲得相同的返回類型? – displayName

+0

JVM靜態實例化-128到127的值,並將這些值保存在內存中以獲得額外性能,稱爲「最常用值」。這消除了一次又一次實例化它們的需要,因爲從緩存中檢索比實例化更快。您將始終獲得相同的返回類型。 – callOfCode

+0

這是我以前不知道的事情。謝謝。這很有用。 – displayName