Java:从 X 到 Y 的未经检查的转换/如何实现castOrNull

发布于 2024-09-27 23:19:04 字数 850 浏览 12 评论 0 原文

我已经实现了这个函数:

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

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

I have implemented this function:

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

This gives me the compiler warning:

Type safety: Unchecked cast from X to Y

Which I don't exactly understand. Isn't the try/catch which I am doing here a check for it? Can I ignore the warning?

Will my function work as expected or not? How would I implement it correctly?

I also tried with a obj instanceof Y check but that doesn't work because of the way Java handle generics.

Btw., this function seems quite useful to me (to make some other code more clean). I wonder if such a function may already exist in Java?


One example where I want to use it:

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

I have cases like these quite often in my code. And I think this is more readable and simpler than anything else. But please give me a better suggestion if you have any about how to make that code even more simple.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

轻许诺言 2024-10-04 23:19:04

所以这里的问题是,通用参数 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;
    }
}

So the problem here is that the generic parameter Y when used for dynamic casting is treated as Object. It will never throw a CCE. You get a CCE thrown in the calling method, as you have broken static type safety.

Also X is entirely pointless here:

Almost certainly the correct solution is not to attempt anything like this. null is bad. Casting is bad.

However, if you are determined to write nonsense, you can pass the Class object:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}
成熟稳重的好男人 2024-10-04 23:19:04

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

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

I'm not entirely sure it will work as expected. (Depends on what you expect of course :-) but this code will for instance result in a java.lang.ClassCastException (ideone):

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 got the "correct" solution.

迷雾森÷林ヴ 2024-10-04 23:19:04

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

您的代码将被编译为:

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

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

Thanks to the way java generics where designed this code wont work at all. Generics are only useful for compile time type checking as the classes don't use generic type information at runtime.

Your code will be compiled to this:

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

The cast to Object will never fail, and the compiled code has no access to the generic types present at compile time. Since the cast does not happen the way it should you receive a warning for an unchecked operation.

跨年 2024-10-04 23:19:04

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

You can suppress the warning in this method if you know for sure that it's not a problem by annotating it with @SuppressWarnings("unchecked")

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文