2013-01-21 33 views
11

我目前正在輔導一位AP Java高中生,她問我一個關於「雙鑄」的問題。我以前從未聽說過這個詞,但顯然她的老師希望她在即將到來的決賽中瞭解它。「雙鑄」

她的老師提供的例子是,如果你想投的整數爲一個字符串,你就必須做到以下幾點不得到一個編譯錯誤:

Integer i = new Integer(5); 
String s = (String)(Object) i; 

的問題是:當你想在現實生活中做到這一點?

老師只提供導致運行時錯誤的例子。另外,我從來不知道這是一個術語,但是這樣做似乎不是個好主意,因爲只有兩種類型不兼容時纔會出現錯誤。

謝謝!

+8

該代碼肯定會導致'ClassCastException',而'Integer'可以 「向上轉型」 爲'Object',該對象仍然知道它是一個「整數」...第二次投射將失敗。她的老師吸菸是什麼? :p – fge

+0

@fge是啊..我想不出任何當她今天問我這個問題時有意義的例子,所以我告訴她我會回到她的身邊..很高興知道這只是一個壞主意,而我我並不瘋狂。 =] –

+0

沒有理由爲什麼你會寫這樣的代碼。如果您知道投射後需要的最終對象類型,那就是您要將對象投入的東西。你確定老師不是指(String)((Object)i).doSomething())嗎? – aishwarya

回答

8

是的,我很確定這不是件事。沒有理由需要雙重鑄造 - 有可能它可能會擺脫關於不安全鑄造的編譯警告(在這種情況下,你可能做錯了),但否則這是不對的。

我的意思是,有自動toString打電話給println("" + i),但即使如此,你並不需要強制轉換爲對象的第一...

編輯:讀湯姆的回答後,我突然不能確定這個答案 - 元和(特別是)仿製藥可以使用這種。我現在沒有能力測試任何東西,但是任何閱讀這個答案的人都應該看看他的(也許是upvote吧)絕對是

然而,我將堅持不存在(或者至少極少數和很少)的理由,但是,所提供的示例肯定與它無關。

+1

+1呼號詭計 – Mikhail

+0

@Jeff我認爲如果有的話,它會添加有關不安全轉型的警告。它可以做的是允許它編譯(儘管這不一定是件好事)。 –

+0

@ TomHawtin-tackline可能 - 我現在沒有任何試驗的方法。你說這不是一件好事 - 任何時候它都允許代碼編譯,否則它就會拋出一個運行時異常(當然,除了編譯器中的錯誤等) – Jeff

1

當然,雖然這只是避免編譯器錯誤,但運行時錯誤必然會發生。同樣,如果兩個類位於繼承層次結構中,則不需要向下轉換到基類並再次向上轉換。

即使在上述問題中,最後還是需要一個API方法來轉換對象。

1

據我所知,在良好的代碼中,你應該從來沒有有一個需要鑄造,除非沒有其他選擇,並且這個顯式鑄造是introducing overheadtoString()是理想的解決方案:

Integer i = new Integer(5); 
String s = i.toString(); 
7

雖然「雙鑄造」肯定不是一個常用詞,你應該似乎沒有任何類型的引用鑄造的話,你應該知道會發生什麼(一ClassCastException)。

爲了完整,也有一些情況下,它不會CCE:

  • 如果該值實際上是null
  • 涉及基元的東西。(ER,ObjectInteger到至[拆箱] int,或int爲[有損] byte爲[正] char
  • 更改通用類型的參數。 List<String>ObjectList<Integer>
+0

Ooooooh,關於int-byte-char的好處 - 這實際上是一個可以做某些事情(潛在地)有用的例子,即使它可以通過其他方式完成。此外,使用泛型類型選項,它是否允許您在每次get()時都使用一個'List '多種類型而不需要投射? – Jeff

+0

@Jeff請不要!儘管'Collection.emptyXyz()'方法家族使用了類似的東西。 –

+0

哦相信我,我不會,但我的回答目前嚴重不正確,我不喜歡有一個不正確的接受答案。 – Jeff

0

也許這個問題是邏輯?我的意思是,有一種方法可以計算某些東西(使用Integers)並返回Object,而使用方法將結果強制轉換爲String,通常這個metod可以重寫幾次,在Java 1.5之前使用了這樣的功能。是否定義了Generic每種方法的CALSS(但沒有泛型),並返回爲對象becasue有幾個孩子的每個人都可以返回自己的類型,我不知道,但可以回答,雙鑄造這樣

public class Main { 
    public static void main(String[] args) { 

     AbstractToDO abstractToDO2 = new SomeToDoTwo(); 
     String result2 = (String) abstractToDO2.toDo(); // here is second, all is good 

     System.out.println(result2); 

     AbstractToDO abstractToDO1 = new SomeToDoOne(); 
     String result1 = (String) abstractToDO1.toDo(); // here is second, Runtime error 

     System.out.println(result1); 

    } 

    Object onePlusOne(){ 

     return 1+1 +" "; 
    } 
} 

interface AbstractToDO{ 
    Object toDo(); 
} 

class SomeToDoOne implements AbstractToDO{ 
    @Override 
    public Object toDo() { 
     return (Object)(1+1); // here is first casting, // we can use without (Object) casting 
    } 
}class SomeToDoTwo implements AbstractToDO{ 
    @Override 
    public Object toDo() { 
     return (Object)"1+1"; // here is first casting, // we can use without (Object) casting 
    } 
} 
0

我已經最近遇到這個問題和它的用處。我有一個具有2個整數值和一個字符串的對象數組。當我解開它時,我需要將整數轉換爲雙精度來進行分割。

問題是,當我來投出整數值來加倍錯誤,因爲Java自動檢測它爲Integer對象不是int原語,並且您不能從整數轉換爲雙倍。

因此,解決方案是在分割之前使用(double)(int)value。因此,總結一下,如果你將int的對象存儲爲對象,並且你想將它轉換爲double來進行某些分割,那麼java會自動將它轉換爲一個整數,使分割變得不可能。

0

雖然在程序員的未來中雙重鑄造看起來可能是冗餘的,但至少知道語法是如何工作的可以幫助您瞭解Java的基本工作原理。

例如:

比方說,一個AnimalDog類的父類。我們知道Object類是所有類的超類。

Dog d = new Dog(); 
Object a = d;   //no errors occur 

這裏,d被隱式鑄造作爲Object對象。顯然,這將是Object a = (Object)d;

這裏呢?

Dog d = new Dog(); 
Object a = (Animal)d; //no errors occur 

我們鑄造d作爲Animal對象,但是編譯器是隱式鑄造它作爲一個Object對象。雙重鑄造。

哪一個是d最終鑄造爲?

明確,這將是Object a = (Object)(Animal)d;

知道雙鑄造的語法,我們會知道d將最終被鑄造爲Object,因此也不會出現錯誤。

0

一個真正的用例是:

static class Y extends X<Date> { 
//some code 
} 

List<Y> n = new ArrayList<>(); 

someMethod((List<X<Date>>)(List<?>) n); 

其中

void someMethod(List<X<Date>>){ 
//some code 
}