55

在某些情况下,让类型转换返回空值而不是抛出 ClassCastException 是切实可行的。C# 具有as执行此操作的运算符。Java中是否有等效的东西,所以您不必显式检查ClassCastException?

4

6 回答 6

61

正如@Omar Kooheji 所建议的,这是as 的实现:

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
于 2008-09-29T14:36:16.167 回答
27

我认为你必须自己动手:

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

编辑:如果您不希望您的客户端代码处理空值,那么您可以引入一个空对象

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
    }
}
于 2008-09-29T14:15:04.657 回答
15

您可以使用instanceof关键字代替 C# 的is,但没有as.

例子:

if(myThing instanceof Foo) {
   Foo myFoo = (Foo)myThing; //Never throws ClassCastException
   ...
}
于 2008-09-29T14:14:14.333 回答
12

您可以像这样编写静态实用程序方法。我认为它的可读性不是很强,但它是您尝试做的最好的近似值。如果你使用静态导入,它在可读性方面也不会太糟糕。

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);
    }
}
于 2008-09-29T14:33:19.247 回答
4

在 java 8 中,您还可以将流语法与 Optional 一起使用:

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"));
于 2016-02-12T08:00:33.277 回答
-3

我推测您可以适当地创建一个 as 运算符

就像是

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

我不知道你会怎么做,我现在是 ac#,自从我离开大学后,我的 Java 帽子变得有点尘土飞扬。

于 2008-09-29T14:16:45.730 回答