在 Java 中转换变量

2022-08-31 11:50:04

我想知道有没有人能告诉我选角是如何工作的?我理解我什么时候应该这样做,但并不是它是如何工作的。对于基元数据类型,我部分理解,但是当涉及到转换对象时,我不明白它是如何工作的。

比方说,一个对象的类型是Object,怎么可能突然被强制转换为(只是一个例子),然后得到所有的方法?MyType


答案 1

在Java中转换不是魔术,而是你告诉编译器A类型的对象实际上是更具体的B类型,从而可以访问B上的所有方法,否则你不会有这些方法。在执行强制转换时,您没有执行任何类型的魔术或转换,您实际上是在告诉编译器“相信我,我知道我在做什么,我可以向您保证,这行中的这个对象实际上是一个<在这里插入强制转换类型>。例如:

Object o = "str";
String str = (String)o;

以上很好,不是魔术,一切都很好。存储在o中的对象实际上是一个字符串,因此我们可以毫无问题地转换为字符串。

这有两种方式可能会出错。首先,如果你在完全不同的继承层次结构中的两种类型之间进行转换,那么编译器会知道你很愚蠢并阻止你:

String o = "str";
Integer str = (Integer)o; //Compilation fails here

其次,如果它们位于同一层次结构中,但仍然是无效的强制转换,则将在运行时抛出 a:ClassCastException

Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here

这实质上意味着您违反了编译器的信任。你已经告诉它你可以保证对象是特定类型的,但事实并非如此。

为什么需要铸造?好吧,首先,您只需要从更通用的类型转到更具体的类型时才需要它。例如,继承自 ,因此,如果要将 a 存储为 a,那也没关系(因为所有整数都是数字)。但是,如果你想反其道而行之,你需要一个强制转换 - 并非所有数字都是整数(以及整数,我们有,,,等)。即使您的项目或JDK中只有一个子类,也可以很容易地创建另一个子类并分发它,因此即使您认为这是一个单一的,显而易见的选择,您也不能保证!IntegerNumberIntegerNumberDoubleFloatByteLong

关于用于转换,您仍然在一些库中看到它的必要性。在Java-5之前,它在集合和其他各种类中被大量使用,因为所有集合都用于添加对象,然后强制转换您从集合中获得的结果。然而,随着泛型的出现,大部分用于转换的用途已经消失了 - 它已经被泛型所取代,它提供了一种更安全的替代方案,没有ClassCastExceptions的潜力(事实上,如果你干净利落地使用泛型并且没有警告地编译,你可以保证你永远不会得到ClassCastException。


答案 2

实际上,选角并不总是有效。如果对象不是要将其强制转换为的类,则在运行时将获得一个。instanceofClassCastException


推荐