2008-09-29 93 views
42

在某些情況下,類型轉換返回空值而非拋出ClassCastException是可行的。 C#有as運算符來執行此操作。在Java中是否有可用的等價物,所以您不必顯式檢查ClassCastException?如何在Java中模擬C#as-operator

回答

47

這裏的,由@Omar Kooheji建議的實現:

public static <T> T as(Class<T> clazz, Object o){ 
    if(clazz.isInstance(o)){ 
     return clazz.cast(o); 
    } 
    return null; 
} 

as(A.class, new Object()) --> null 
as(B.class, new B()) --> B 
13

您可以使用instanceof關鍵字代替C#的is,但沒有什麼像as

例子:

if(myThing instanceof Foo) { 
    Foo myFoo = (Foo)myThing; //Never throws ClassCastException 
    ... 
} 
+9

是的,老雙演員。恥辱Java沒有像'as'那樣優雅的東西。 – 2008-09-29 14:14:59

+1

'as'是一個非常有用的東西。 – 2008-09-29 14:16:03

25

我倒是覺得你必須推出自己的:

return (x instanceof Foo) ? (Foo) x : null; 

編輯:如果你不想讓你的客戶端代碼來處理空值,然後你可以引入一個Null Object

interface Foo { 
    public void doBar(); 
} 
class NullFoo implements Foo { 
    public void doBar() {} // do nothing 
} 
class FooUtils { 
    public static Foo asFoo(Object o) { 
     return (o instanceof Foo) ? (Foo) o : new NullFoo(); 
    } 
} 
class Client { 
    public void process() { 
     Object o = ...; 
     Foo foo = FooUtils.asFoo(o); 
     foo.doBar(); // don't need to check for null in client 
    } 
} 
-2

我猜測,你可以propably CREAS一個作爲運營商

as<T,Type> (left, right) 
which evaluates to 
if (typeof(left) == right) 
    return (right)left 
else 
    return null 

我不知道你是怎麼做到的,我是一個C#的時刻,因爲我離開了我大學的Java帽子已經變得有點髒。

+1

具體類型比較,即`typeof(left)== right`不是`as`所做的。 – weston 2013-09-06 08:31:02

10

你可以編寫一個像這樣的靜態工具方法。我不認爲這是非常可讀的,但它是你想要做的最好的近似。如果你使用靜態導入,它的可讀性不會太差。

package com.stackoverflow.examples; 
public class Utils { 
    @SuppressWarnings("unchecked") 
    public static <T> T safeCast(Object obj, Class<T> type) { 
     if (type.isInstance(obj)) { 
      return (T) obj; 
     } 
     return null; 
    } 
} 

以下是一個演示它是如何工作的測試案例(以及它的工作。)

package com.stackoverflow.examples; 
import static com.stackoverflow.examples.Utils.safeCast; 
import static junit.framework.Assert.assertNotNull; 
import static junit.framework.Assert.assertNull; 

import org.junit.Test; 

public class UtilsTest { 

    @Test 
    public void happyPath() { 
     Object x = "abc"; 
     String y = safeCast(x, String.class); 
     assertNotNull(y); 
    } 

    @Test 
    public void castToSubclassShouldFail() { 
     Object x = new Object(); 
     String y = safeCast(x, String.class); 
     assertNull(y); 
    } 

    @Test 
    public void castToUnrelatedTypeShouldFail() { 
     Object x = "abc"; 
     Integer y = safeCast(x, Integer.class); 
     assertNull(y); 
    } 
} 
+0

這實際上不起作用。 isAssignableFrom測試以查看obj是否是T超類的實例。因此,safeCast(new Object(),A.class).doA()將返回類轉換異常,而不是NPE。 – 2008-09-29 14:43:40

0

在java 8中,您還可以使用可選的流語法:

Object o = new Integer(1); 

Optional.ofNullable(o) 
     .filter(Number.class::isInstance) 
     .map(Number.class::cast) 
     .ifPresent(n -> System.out.print("o is a number"));