我已经实现了此功能:

 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();
        }
    }

我的代码经常有这样的案例。而且我认为这比其他任何事情都更可读和简单。但是,如果您对如何使该代码更加简单,请给我一个更好的建议。

有帮助吗?

解决方案

因此,这里的问题是通用参数 Y 当用于动态铸造时被视为 Object. 。它永远不会抛出CCE。你会被扔在 打电话 方法,因为静态型安全性破裂。

X 在这里完全毫无意义:

几乎可以肯定的是,正确的解决方案不是尝试这样的事情。 null 不好。铸造很糟糕。

但是,如果您决心写废话,则可以通过 Class 目的:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}

其他提示

我不确定它会按预期工作。 (取决于您的期望:-)但是,例如,此代码将导致 java.lang.ClassCastException (伊德尼):

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得到了 “正确”解决方案.

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

多亏了Java Generics设计该代码根本无法正常工作的方式。仿制药仅对编译时间类型检查有用,因为类在运行时不使用通用类型信息。

您的代码将被编译为:

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

对象的演员将永远不会失败,并且编译的代码无法访问编译时存在的通用类型。由于演员阵容不会像您收到未经检查操作的警告那样发生。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top