2012-08-22 156 views
3

比如我有一個Object「假裝」是String有沒有辦法避免Java的awkard對象轉換語法?

Object o = new String("dsadsa"); 

如果我想使用該對象的字符串函數,首先我必須將它轉化成一個像這樣的字符串:

((String)o).indexOf("sad"); 

當有這麼多的括號時,這會變得非常煩人和難以理解!特別是當它必須進入IF語句或函數時!

if (((String)o).equals("dsadsa")) {} 

什麼是避免這種情況的最好方法?

+4

爲什麼你有一個'Object'如果你知道它的一個'String'?順便說一句,你不需要在這裏或其他地方使用'new String(String)'。 –

+0

是的,我知道,'新的String()'只是一個例子,真正表明該對象是一個字符串,而且,我很樂意避免這個,但是當我使用'Vector'例如,我想存儲字符串,他們都是對象,所以我沒有選擇。 :/ – SmRndGuy

+0

如果您使用Vector來存儲_store_字符串,則不需要轉換。一個字符串是一個對象,所以它會工作。但是如果你使用的是矢量,除非你使用j2me或者java 1.4,你可以使用矢量,或者甚至ArrayList 將(可能)更好地爲你服務 –

回答

8

將該對象投射到一行中。

在另一行中使用鑄造對象。

9

一個解決方案是確保您的對象是一個精確的類,例如在您的方法的原型。

這是最好的做法,因爲它也有助於避免運行時錯誤。

參數化類(泛型)越來越容易。

否則表示:如果您的代碼中有很多強制轉換,則可能存在設計問題。但是我們需要更多代碼來提出解決方案。

7

在實踐中,正確使用泛型會擺脫您在代碼中看到的大多數表演。

但是,如果由於某種原因,你不能這樣做(較舊的Java版本,舊版庫),創造一個你儘早投一個局部變量。

一個特殊情況是當您將一個對象從接口類型轉換爲其實現時。這幾乎總是錯誤的,並且意味着界面設計得不好。

+0

似乎泛型比我以前認爲的重要得多。太糟糕了我無法使用它,因爲我實際上是在不支持泛型的JavaME中進行編程。 x_x 我相信我應該使用第二個選項。 – SmRndGuy

+0

我假設你真的擺脫了括號後。如果你想完全擺脫這些演員陣容,仿製藥就是你所追求的(如果他們對你有用)。 – Hbcdev

5

的標準做法是始終捕捉對象插入到窄類型的變量,在你的情況下,String str變量,並使用它之後。

請注意,在你的第三個例子中,你不需要downcast:o.equals(o2)也可以。

如果您決定學習Java泛型,您可能會很快失望:他們通常會將冗長度從向下轉換爲類型聲明。當重寫到泛型時,許多代碼片段都很長,並且有些代碼段甚至更長。

+1

+1表示在示例中甚至不需要鑄造。我認爲儘管泛型確實是冗長的,但它們更易於閱讀和解釋。 – biziclop

+0

@biziclop它隨使用情況而變化 - 集合類型是一種勝利,尤其是與增強型相結合。另一方面,用作lambda函數的回調是相當失敗的,因爲類型推斷很弱。 –

+0

至少在java 7中,它不是詳細描述:列表 list = new ArrayList ()成爲列表 list = new ArrayList <>(); – Matt

1

我不這麼認爲。您必須明確地將超類轉換爲子類。

String str; 

if(o instanceOf String){ 
    str =(String)o; 
    str.indexOf("sad"); 
    ... 
} 
+0

這個解決方案的麻煩,除了更難閱讀的是,如果o不是'String',你會得到一個NPE而不是'ClassCastException',這對代碼維護者來說是非常混亂的。 – biziclop

+0

如果您要測試'instanceof String'(注意:instanceof中的'o'小),那麼之前單獨測試'o!= null'沒有意義。無論按照預期情況,「無論什麼」都是「假」。 (除此之外,我不太清楚你在這裏實際處理的是什麼。) –

+0

@ arne.b - 謝謝糾正 –

1

你可以做一些危險的事情,趁着泛型像

public static <T> T cast(Object o){ 
    return (T) o; 
} 

這允許你做不喜歡的東西

Object o=""; 
String s = cast(o); 

這是真的哈克,但你可以做類似

public static String s(Object o){ 
    return (String) o; 
} 

然後

Object o = ""; 
    s(o).indexOf("sad"); 
2

我假設你的意思是說你String是假裝的Object

你的句柄是Object類型的,它不需要。

  1. 如果您使用的是Object類型,因爲這是你的方法獲取參數,考慮更改參數類型爲String,如果你實際上是在期待一個字符串。
  2. 如果這來自集合,請考慮更改集合以使用泛型,以便您可以將集合定義爲String類型。
  3. 如果由於某些原因您無法更改進入的對象的類型,請確認它實際上是一個String,然後將其轉換爲另一個String類型的變量。

這是代碼的樣子,第三個選項。

String s; 
if (o instanceof String) { 
    s = (String) o; 
} else { 
    s = null; 
    throw new IllegalArgumentException(); 
    // Or take some corrective action. 
} 
1

我不建議這樣做,但你可以此:

String.class.cast(o).indexOf("sad"); 
0

看來你不想編譯時類型檢查。 然後,只需使用腳本語言,例如Groovy也運行在JVM上,但不需要靜態類型。

0

"dsadsa".equals(someString)是如何完成的 - 即使someString實際上被聲明爲對象,它也會有效地消除NPE的機會並確保不會發生虛擬呼叫。

另外你不需要劇組就可以致電equals()

除此之外,你可以使用泛型,但他們過於冗長的語法,尤其當涉及到的東西像<T extends Foo &Bar> T selectFooBared(List<java.lang.ref.Reference<T>> list, Comparator<? super T> c);

相關問題