我最近偶然发现了一段代码:
Object o = .. ;
Foo foo = Foo.class.cast(o);
我实际上甚至都不知道java.lang.Class有一个强制转换方法,所以我查看了文档,从我收集的内容中,这只是对类对象所代表的类进行强制转换。所以上面的代码大致相当于
Object o = ..;
Foo foo = (Foo)o;
所以我想知道,为什么我会想要使用强制转换方法而不是简单地使用“旧方法”进行转换。有没有一个很好的例子,使用cast方法比使用简单的强制转换更有益?
答案 0 :(得分:7)
我不认为它经常与你所展示的完全一致。我见过的最常见的用途是使用泛型的人试图做的相当于:
public static <T extends Number> T castToNumber(Object o) {
return (T)o;
}
由于类型擦除,它实际上没有任何用处。
虽然这是有效的,并且类型安全(模ClassCastExceptions
):
public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
return clazz.cast(o);
}
编辑:使用google guava的几个例子:
答案 1 :(得分:4)
在Java中,通常有不止一种方法可以为猫提供皮肤。在您拥有框架代码的情况下,此类功能可能很有用。想象一个接受Class对象实例和Object实例的方法,并将Object case作为类返回:
public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
{
SomeBaseClass castObj = whatToCastAs.cast(o);
castObj.doSomething();
}
一般情况下,使用更简单的铸造,除非它不够。
答案 2 :(得分:2)
在某些情况下,您只知道在运行时将对象强制转换为的类型,并且必须使用强制转换方法。
答案 3 :(得分:2)
绝对没有理由写Foo.class.cast(o)
,它相当于(Foo)o
。
一般情况下,如果X
是可再生类型和Class<X> clazz
,则clazz.cast(o)
与(X)o
相同。
如果所有类型都可以恢复,则方法Class.cast()
因此是多余的,无用的。
不幸的是,由于当前版本的Java中的擦除,并非所有类型都可以恢复。例如,类型变量不可恢复。
如果T
是类型变量,则取消选中强制转换(T)o
,因为在运行时,JVM不知道T
的确切类型,JVM无法测试o
实际上是T
类型。可能会错误地允许演员表,这可能会在以后引发问题。
这不是一个大问题;通常当程序员执行(T)o
时,他已经推断出强制转换是安全的,并且在运行时不会引起任何问题。应用程序逻辑检查 。
假设在演员阵容中有Class<T> clazz
可用,那么我们就知道T
在运行时是什么;我们可以添加额外的运行时检查,以确保o
确实是T
。
check clazz.isInstance(o);
(T)o;
这基本上是Class.cast()
所做的。
我们永远不会指望演员阵容在任何情况下失败,因此在正确实施的应用中,支票clazz.isInstance(o)
必须始终成功,因此clazz.cast(o)
相当于(T)o
- 再次,假设代码是正确的。
如果可以证明代码是正确的并且演员阵容是安全的,那么出于性能原因,可能会更喜欢(T)o
到clazz.cast(o)
。在另一个答案中提出的MutableClassToInstanceMap
示例中,我们可以看出演员阵容是安全的,因此简单(T)o
就足够了。
答案 4 :(得分:1)
class.cast是为泛型类型设计的。
使用泛型参数T构造类时,可以传入一个 类。然后,您可以使用静态和动态进行演员 检查,哪(T)不给你。它也不会产生未检查 警告,因为它被检查(在那一点)。
答案 5 :(得分:1)
通用示例是从持久层检索使用类对象和某些条件引用的实体集合。返回的集合可能包含未经检查的对象,因此如果您只是将其强制转换为指向G_H,则此时将抛出Cast Exception,而不是在访问值时抛出。
这方面的一个示例是,当您从DAO检索一个返回未经检查的集合的集合时,您在服务上迭代它,这种情况可能导致ClassCastException。
解决它的一种方法,因为你有想要的类和未经检查的集合迭代它并将它转换到DAO中转换集合在一个已检查的集合中,然后返回它。
答案 6 :(得分:0)
因为你可能有这样的东西:
Number fooMethod(Class<? extends Number> clazz) {
return clazz.cast(var);
}
答案 7 :(得分:0)
Java中的“强制转换”,例如(Number)var
,括号内的东西是引用类型,实际上由两部分组成:
ClassCast Exception
(如果你要转换的东西是一个类型变量,那么它检查的类将是类型变量的下限)要使用语法,您需要在编写代码时了解该类。假设您在编译时不知道要转换为哪个类;你只能在运行时知道它。
现在你会问,那么铸造的重点是什么?在编译时是不是要将表达式转换为所需类型的转换点?所以如果你在编译时不知道类型,那么在编译时没有任何好处,对吧?没错,但这只是上面的第一项。您忘记了演员表的运行时组件(上面的第二项):它根据类检查对象。
因此,运行时强制转换(即Class.cast()
)的目的是检查该对象是否为该类的实例,如果不是,则抛出异常。它大致相当于此但更短:
if (!clazz.isInstance(var))
throw new ClassCastException();
有些人提到Class.cast()
也有一个很好的返回类型,它基于传入的类的类型参数,但这只是一个由编译时强制转换提供的编译时功能无论如何。因此,为此目的,使用Class.cast()