我想知道是否有人能告诉我铸造是如何工作的?我知道什么时候应该这样做,但不知道它是如何工作的.在原始数据类型上我部分理解但是当涉及到投射对象时,我不明白它是如何工作的.
一个具有Object类型的对象如何突然被强制转换为MyType(仅举例)然后获取所有方法?
Mic*_*rry 174
使用Java进行转换并不神奇,它是告诉编译器类型A的对象实际上是更具体的类型B,因此可以访问B上的所有其他方法.你在执行转换时没有执行任何魔法或转换,你实际上是告诉编译器"相信我,我知道我在做什么,我可以保证你在这一行的这个对象实际上是一个<Insert cast在这里输入>." 例如:
Object o = "str";
String str = (String)o;
Run Code Online (Sandbox Code Playgroud)
以上是好的,不是魔术,一切都很好.存储在o中的对象实际上是一个字符串,因此我们可以毫无问题地转换为字符串.
有两种方法可能出错.首先,如果你在完全不同的继承层次结构中的两种类型之间进行转换,那么编译器就会知道你是愚蠢的并阻止你:
String o = "str";
Integer str = (Integer)o; //Compilation fails here
Run Code Online (Sandbox Code Playgroud)
其次,如果它们处于相同的层次结构中但仍然是无效的转换,那么ClassCastException将在运行时抛出:
Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here
Run Code Online (Sandbox Code Playgroud)
这实际上意味着您违反了编译器的信任.你告诉它你可以保证对象属于特定类型,但事实并非如此.
你为什么需要铸造?好吧,从一开始就只需要从更通用的类型到更具体的类型.例如,Integer继承自Number,所以如果你想存储Integer一个Number那么没关系(因为所有整数都是数字.)但是,如果你想反过来需要一个演员 - 不是所有的数字都是整数(以及作为整数我们有Double,Float,Byte,Long等),即使在你的项目或JDK只是一个子类,有人可以很容易地创建另一个和分发,所以,你不能保证,即使你认为这是一个单一的,显而易见的选择!
关于铸造的使用,你仍然看到在某些库中需要它.在Java-5之前,它在集合和各种其他类中被大量使用,因为所有集合都在处理添加对象,然后将结果转换回集合.然而,随着仿制药的出现,大部分用于铸造的东西已经消失 - 它已经被泛型替代,它提供了更安全的替代方案,没有ClassCastExceptions的潜力(事实上如果你干净地使用泛型并且它没有警告就编译,你可以保证你永远不会得到ClassCastException.)
假设您想要转换String为a File(是的,它没有任何意义),您不能直接转换它,因为File该类不是子类而不是类的父String类(并且编译器会抱怨).
但是你可以投你String来Object,因为String是一个Object(Object是父母).然后你可以将这个对象转换为a File,因为File是一个Object.
因此,在编译时从打字的角度来看,所有操作都是"合法的",但这并不意味着它将在运行时工作!
File f = (File)(Object) "Stupid cast";
Run Code Online (Sandbox Code Playgroud)
即使它没有意义,编译器也会允许它,但它会在运行时因此异常而崩溃:
Exception in thread "main" java.lang.ClassCastException:
java.lang.String cannot be cast to java.io.File
Run Code Online (Sandbox Code Playgroud)