在Java中进行转换并不奇怪,它告诉编译器A类型的对象实际上是更具体的类型B,因此获得了你不会有的B上的所有方法。你在执行转换时没有执行任何类型的魔法或转换,你基本上告诉编译器“相信我,我知道我在做什么,我可以保证,这一行的这个对象实际上是一个
Object o = "str";
String str = (String)o;
上面是罚款,不是魔术,一切顺利。存储在o中的对象实际上是一个字符串,因此我们可以转换为一个字符串没有任何问题。
有两种方法可能会出错。首先,如果你在完全不同的继承层次结构中的两种类型之间进行转换,那么编译器会知道你是愚蠢的,并阻止你:
String o = "str";
Integer str = (Integer)o; //Compilation fails here
其次,如果它们在同一个层次结构中,但仍然是无效的转换,那么在运行时将抛出ClassCastException:
Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here
这本质上意味着你违反了编译器的信任。你已经告诉它,你可以保证对象是一个特定的类型,而不是。
为什么需要铸造?好吧,从你开始只需要它从一个更一般的类型到一个更具体的类型。例如,Integer继承自Number,所以如果你想把一个Integer存储为一个Number,那么这就是确定的(因为所有的Integer都是数字。)然而,如果你想要反过来,你需要一个转换 – 不是所有的数字整数(以及整数,我们有Double,Float,Byte,Long等)即使你的项目或JDK只有一个子类,有人可以很容易地创建另一个并分发,所以你不能保证即使你认为这是一个单一的,明显的选择!
关于使用铸造,你仍然看到需要在一些图书馆。 Pre Java-5它在集合和各种其他类中被大量使用,因为所有集合都在添加对象,然后投射您收回的结果。然而,随着泛型的出现,许多铸造的用途已经消失了 – 它已被替代为泛型,提供了一个更安全的替代方法,没有潜在的ClassCastExceptions(事实上,如果你使用泛型干净,它编译没有警告,你有一个保证,你永远不会得到一个ClassCastException。)