Java泛型

时间:2009-03-11 17:52:36

标签: java generics casting

我想实现一个以Object为参数的方法,将其强制转换为任意类型,如果失败则返回null。这是我到目前为止所做的:

public static void main(String[] args) {
    MyClass a, b;
    a = Main.<MyClass>staticCast(new String("B"));
}

public static class MyClass {
}

public static <T> T staticCast(Object arg) {
    try {
        if (arg == null) return null;
        T result = (T) arg;
        return result;
    } catch (Throwable e) {
        return null;
    }
}

不幸的是,类型强制转换异常永远不会被抛出/捕获到staticCast()函数的主体中。似乎Java编译器生成函数String staticCast(Object arg),其中你有一行String result = (String) arg;,即使我明确地说模板类型应该是MyClass。有帮助吗?感谢。

5 个答案:

答案 0 :(得分:10)

因为泛型类型信息在运行时被擦除,所以转换为泛型类型的标准方法是使用Class对象:

public static <T> T staticCast(Object arg, Class<T> clazz) {
    if (arg == null) return null;
    if (!clazz.isInstance(arg))
        return null;
    T result = clazz.cast(arg);
    return result;
}

然后这样称呼:

a = Main.staticCast("B", MyClass.class);

答案 1 :(得分:6)

你不能做你想要的......至少不是这样。编译器删除了所有信息,因此您最终将(T)作为演员中的对象 - 并且可以正常工作。

问题是以后你正在做MyClass =(String)对象;这是不允许的。

您绕过了编译器检查并使其在运行时失败。

那你究竟想做什么呢?如果你告诉我们你为什么要这样做,我们可能会告诉你Java的做法。

鉴于您的评论,您可以尝试以下方式:

public class Main
{
    public static void main(String[] args)
    {
        String a;
        MyClass b;
        a = staticCast(new String("B"), String.class);
        b = staticCast(new String("B"), MyClass.class);
        System.out.println(a);
    }

    public static class MyClass
    {
    }

    public static <T> T staticCast(Object arg, final Class clazz)
    {
        // edit - oops forgot to deal with null...
        if(arg == null)
        {
            return (null);
        }

        // the call to Class.cast, as mmeyer did, might be better... probably is better... 
        if(arg.getClass() != clazz)
        {
            // Given your answer to Ben S...
            return (null);

            // throw new ClassCastException("cannot cast a " + arg.getClass() + " to a " + clazz);
        }

        return ((T)arg);
    }
}

答案 2 :(得分:4)

你的意思是Class<T>.cast(Object obj)

类似的东西:

Class.forName("YourClass").cast(obj);

应该做你想做的事。

请注意,这是非常臭的,可能是设计不佳的迹象。

答案 3 :(得分:1)

不要将Java泛型误认为是C ++模板。只有一个staticCast方法被调用不同类型的擦除,而不是每个T都有一个。

根本不使用Generics,我会这样写:

public static void main(String[] args) {
    MyClass a, b;
    a = (MyClass)Main.staticCast(new String("B"), MyClass.class);
}

public static class MyClass {
}

public static staticCast(Object arg, Class class) {
        if (arg != null && class.isAssignableFrom(arg))
          return arg;
        return null;
}

或者从另一个答案中窃取,使用泛型:

public static <T> T staticCast(Object arg, Class<T> class) {
        if (arg != null && class.isAssignableFrom(arg))
        {
           T result = class.cast(arg);
           return result;
        }
        return null;
}

答案 4 :(得分:1)

我同意本,但是,我更喜欢以下符号:

MyClass.class.cast(obj);