Java中与C#关键字'as'相当的是什么?

29
在Java中,如果转换失败,尝试强制转换并获取null是否可行?
9个回答

56
public static <T> T as(Class<T> t, Object o) {
  return t.isInstance(o) ? t.cast(o) : null;
}

使用方法:

MyType a = as(MyType.class, new MyType());   
// 'a' is not null

MyType b = as(MyType.class, "");   
// b is null

2
设计不错,但在这种情况下使用isAssignableFrom会更好。 - C. Ross
1
@erickson 它只是处理了一些更多的边缘情况。请参见 Q496928 - C. Ross
我喜欢上述函数 as 的设计,但是让我困扰的是使用 Class 类的 cast 方法会导致 isInstance 方法被调用两次。在内部,该方法使用 IsIsntance 方法来检查类型之间的兼容性。尽管如此,我们可以期望 JVM 可能会内联给定的 as 函数中的 cast 代码,并且 JIT 可能会删除对 IsInstance 方法的冗余调用,但我们无法确定这一点。 - Miguel Gamboa
“as”关键字即使输入对象不是所请求类型的实例也可以工作——如果有任何可能的转换,它都会进行。我对Java还很陌生,但上面的代码会这样做吗?如果不是,那么@C.Ross可能有一个有效的观点。尽管如此,检查null也是必需的(而且并不复杂)。 - BrainSlugs83
1
@BrainSlugs83,看起来这种方法有点不如真正的as运算符,因为它不会执行任何类型强制转换。至于C.Ross的评论,他的建议与此问题无关,他没有解释其中的任何好处。 - erickson
显示剩余3条评论

30

您可以使用 instanceof 关键字来确定是否可以正确地进行类型转换。

return obj instanceof String?(String)obj: null;
当然可以将其泛型化并制成函数,但我认为问题是关于Java必须实现这一点的含义。

1
我不确定这是否是shoosh想要的。可能需要一种更通用的方式来处理强制转换。虽然这对于“如何验证我的对象是给定类的实例”是完美的答案 :) - OscarRyz
1
我认为我们在这里不是为了替别人解决问题,而是提供指导。因此,指出正确的方向就足够了。 - Eugene Ryzhikov

5
你可以使用Java中的多个函数来实现,但无法使用单个函数:
public B nullCast(Object a) {

  if (a instanceof B) {
     return (B) a;
  } else {
     return null;
  }
}

编辑:请注意,如果不添加目标类,您无法使B类成为泛型类(针对此示例)。这是因为泛型类型在instanceof中不可用。

public <V, T extends V> T cast(V obj, Class<T> cls) {
  if (cls.isInstance(obj)) {
    return cls.cast(obj);
  } else {
    return null;
  }
}

是的,但我只是提供了一个概括性的想法,而不是具体的方法。 - Kathy Van Stone

2
MyType e = ( MyType ) orNull( object, MyType.class );
// if "object" is not an instanceof MyType, then e will be null.

...

public static Object orNull( Object o , Class type ) { 
    return type.isIntance( o ) ? o : null;
}

我想这个也可以用泛型来完成,但我认为这可能不是所需的。

这个简单的方法接收一个对象并返回一个对象,因为类型转换在方法客户端中执行。


0

以上两种解决方案都有些笨拙:

强制类型转换和捕获ClassCastException:创建异常对象可能很昂贵(例如计算堆栈跟踪)。

前面描述的nullCast方法意味着您需要为每个要执行的转换编写一个转换方法。

由于“类型擦除”,泛型会让您失望...

您可以创建一个静态辅助方法,该方法保证返回目标类的实例或null,然后无需担心异常即可进行转换:

public static Object nullCast(Object source, Class target) {
    if (target.isAssignableFrom(source.getClass())) {
        return target.cast(source);
    } else {
        return null;
    }
}

示例调用:

Foo fooInstance = (Foo) nullCast(barInstance, Foo.class);

0
在Java中,如果强制类型转换失败,将会抛出ClassCastException异常。您可以捕获该异常并将目标对象设置为null。

0

你可以捕获异常:

Foo f = null;
try {
  f = Foo(bar);
}
catch (ClassCastException e) {}

或者检查类型:

Foo f = null;
if (bar instanceof Foo)
  f = (Foo)bar;

3
空的 catch 块是一个非常糟糕的习惯……其实,我认为编译器在你这样做时应该扇你一巴掌;). 无论如何,你永远不应该依赖异常来检查可以在不抛出异常的情况下检查的内容。 - Thomas Levesque
2
这就是为什么我也提供了没有异常的版本。 - Pesto

-1
据我所知,这将是实现此目的的一种方法:
SomeClassToCastTo object = null;
try {
  SomeClassToCastTo object = SomeClassToCastTo.class.cast(anotherObject);
}
catch (ClassCastException e) {
  object = null;
}

虽然不太美观,但应该能实现你想要的功能...


这不是使用反射“cast()”方法的好例子。请参阅https://dev59.com/t3VC5IYBdhLWcg3wlyQo以获取更多信息。 - erickson
同意,我有个脑抽,忘记了 instanceof 运算符。 - Peter
1
在这种情况下可以避免创建异常。异常是对象,因此最好不要不必要地创建它们。 - cd1

-1

你可以处理这个捕获 ClassCastException 的异常


2
每次抛出异常时,都会涉及大量开销。这就是为什么异常应该只是一个“例外”。异常处理应该保留给真正异常的事件。当异常成为规则时,你的编程方式就是错误的。更好的方法是使用类型检查。 - StriplingWarrior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接