6

我已经实现了这个功能:

 static <X,Y> Y castOrNull(X obj) {
  try {
   return (Y)obj;
  }
  catch(ClassCastException e) {
   return null;
  }
 }

这给了我编译器警告:

Type safety: Unchecked cast from X to Y

我不太明白。try/catch我在这里做的不是检查吗?我可以忽略警告吗?

我的功能会按预期工作吗?我将如何正确实施它?

我也尝试过obj instanceof Y检查,但由于 Java 处理泛型的方式,它不起作用。

顺便说一句,这个函数对我来说似乎很有用(使其他一些代码更干净)。我想知道Java中是否已经存在这样的功能?


我想使用它的一个例子:

    void removeEmptyRawStrings() {
        for(Iterator<Entity> e = entities.iterator(); e.hasNext();) {
            RawString s = castOrNull(e.next());
            if(s != null && s.content.isEmpty()) e.remove();
        }
    }

我的代码中经常出现这样的情况。而且我认为这比其他任何东西都更具可读性和简单性。但是,如果您有任何关于如何使该代码更简单的建议,请给我一个更好的建议。

4

4 回答 4

11

所以这里的问题是,Y用于动态转换的泛型参数被视为Object. 它永远不会抛出 CCE。由于破坏了静态类型安全,因此在调用方法中会抛出 CCE 。

在这里也X完全没有意义:

几乎可以肯定,正确的解决方案是不要尝试这样的事情。null不好。选角很差。

但是,如果您确定要写废话,则可以传递Class对象:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}
于 2010-10-14T13:50:45.763 回答
4

我不完全确定它会按预期工作。(当然取决于您的期望:-)但是此代码将例如导致java.lang.ClassCastExceptionideone):

public class Main {

    public static void main(String[] args) {
        Integer o = Main.<String, Integer>castOrNull("hello");
    }


    public static <X, Y> Y castOrNull(X obj) {
        try {
            return (Y) obj;
        } catch (ClassCastException e) {
            return null;
        }
    }
}

@Tom Hawtin 得到了“正确”的解决方案

于 2010-10-14T13:31:08.263 回答
1

如果您确定这不是问题,则可以在此方法中抑制警告,方法是使用注释@SuppressWarnings("unchecked")

于 2010-10-14T13:31:03.343 回答
1

由于设计此代码的Java泛型方式根本无法工作。泛型仅对编译时类型检查有用,因为类在运行时不使用泛型类型信息。

您的代码将编译为此:

 static Object castOrNull(Object obj) {
  try {
   return (Object)obj;//FAIL: this wont do anything
  }
  catch(ClassCastException e) {
   return null;
  }
 }

转换为 Object 永远不会失败,并且编译后的代码无法访问编译时存在的泛型类型。由于强制转换不会按照您收到未经检查操作的警告的方式发生。

于 2010-10-14T14:02:57.523 回答