我想知道是否有人可以告诉我铸造的工作原理?我知道何时应该执行此操作,但并不真正了解它的工作原理。对于原始数据类型,我会部分理解,但是在涉及对象转换时,我并不了解它是如何工作的。
例如,如何突然将类型为Object的对象转换为对象MyType
(仅作为示例),然后获取所有方法?
我想知道是否有人可以告诉我铸造的工作原理?我知道何时应该执行此操作,但并不真正了解它的工作原理。对于原始数据类型,我会部分理解,但是在涉及对象转换时,我并不了解它是如何工作的。
例如,如何突然将类型为Object的对象转换为对象MyType
(仅作为示例),然后获取所有方法?
Answers:
用Java进行强制转换不是魔术,而是告诉编译器A类型的Object实际上是更特定的B类型,因此可以访问B上所有其他方法。在执行强制转换时,您没有执行任何魔术或转换操作,实际上是在告诉编译器“相信我,我知道我在做什么,并且我可以向您保证此行上的此Object实际上是<Insert cast在这里输入>。” 例如:
Object o = "str";
String str = (String)o;
以上很好,不是魔术,一切都很好。存储在o中的对象实际上是一个字符串,因此我们可以将其转换为字符串而不会出现任何问题。
有两种方法可能会出错。首先,如果要在完全不同的继承层次结构中的两种类型之间进行转换,则编译器将知道您是愚蠢的并阻止您:
String o = "str";
Integer str = (Integer)o; //Compilation fails here
其次,如果它们在相同的层次结构中但仍然是无效的强制转换,则ClassCastException
在运行时将抛出a :
Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here
这实质上意味着您已经违反了编译器的信任。您已经告诉您可以保证对象是特定类型的,但事实并非如此。
为什么需要铸造?好吧,首先,只有在从更一般的类型变为更具体的类型时才需要它。例如,Integer
继承自Number
,因此,如果您要存储一个Integer
as,Number
那么就可以了(因为所有的Integers都是Numbers。)但是,如果要沿相反的方向进行转换,则需要强制转换-并非所有Numbers都是Integers(同样作为整数我们有Double
,Float
,Byte
,Long
等),即使在你的项目或JDK只是一个子类,有人可以很容易地创建另一个和分发,所以,你不能保证,即使你认为这是一个单一的,显而易见的选择!
关于强制转换,您仍然可以在某些库中看到对它的需求。在Java-5之前的版本中,它在集合和各种其他类中大量使用,因为所有集合都工作在添加对象,然后转换结果以使您退出集合。但是,随着泛型的出现,铸造的许多用途已不复存在-它已被泛型所取代,泛型提供了一种更安全的替代方法,而没有潜在的ClassCastExceptions(实际上,如果您干净地使用泛型并且编译时没有警告,您可以保证永远不会收到ClassCastException。)
Double.valueOf(gpsLastLoc.getLatitude()).getClass().getSimpleName()
。在这两种情况下,您都不需要动态获取基元的类,因为如果getLatitude()
返回一个双基元,您始终知道它将提升为Double
对象。
假设您想将a强制转换String
为a File
(是的,没有任何意义),则不能直接对其进行强制转换,因为File
该类不是该对象的子级,也不是其父级String
级(并且编译器抱怨)。
但是您可以将您强制转换String
为Object
,因为aString
是Object
(Object
是父级)。然后,您可以将此对象转换为File
,因为File是Object
。
所以从编译的角度来看,所有操作都是合法的,但这并不意味着它将在运行时起作用!
File f = (File)(Object) "Stupid cast";
即使没有意义,编译器也会允许这样做,但是会在运行时因以下异常而崩溃:
Exception in thread "main" java.lang.ClassCastException:
java.lang.String cannot be cast to java.io.File
仅当引用instanceof
类型时,该类型才会起作用。您不能投放随机引用。另外,您需要阅读有关的更多信息Casting Objects
。
例如
String string = "String";
Object object = string; // Perfectly fine since String is an Object
String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.