如果我们可以将 Integer 对象类型转换为 Object 并将 Integer 拆箱为 int,为什么我们不能将相同的对象拆箱到 int?



如果我们可以将 Integer 对象类型转换为 Object 并将 Integer 拆箱为 int,为什么我们不能将相同的 Object 类型拆箱为 int?

Integer i=new Integer(5);
Object p=i;
int s=p;//gives error

编译器不知道Object类型的东西实际上是一个整数。在您的眼睛中,您可以清楚地看到您正在分配一个整数并将其转换为整数对象。但是,一旦您将其分配给Object,由于源代码的语义目的,该信息就会丢失。

这与此代码错误的原因相同:

Object o = getSomeObject();  // What exactly does it return? We don't know
int i = o;                   // How do you know this will work?

函数getSomeObject()可以返回任何内容。我们不知道它会是一个整数,还是一个字符串,或者一个数组列表......因此,我们必须假设这是一种不安全的转换。如果上述内容对您有意义,那么您可以推断出为什么您无法进行转换。

现在,我认为让您感到困惑的部分是"我清楚地在其中放了一个整数,它会自动装箱到Integer中,并且应该可以通过拆箱来分配!

。但是,语言规则规定,一旦我们完成了该作业,我们必须将其视为可以是该类型的任何对象。由于我们不能盲目地假设对象是一个整数,因此您需要显式强制转换它。

这也在多态性的层次结构链中发挥作用。如果你有一个父 P,以及一个从 P 延伸的子 C,那么我们知道:

Child c = new Child();
Parent p = c;  // Valid, because c is definitely a Parent

Parent p = new Parent();
Child c = p;   // Can't go down the hierarchy, this is also wrong

在您的示例中也可以看到同样的事情。IntegerObject的孩子,这就是为什么我们可以这样做

Integer i = 5;
Object o = i;

同样,我们不能反过来做

Object o = new Object();
Integer i = o;  // Not allowed

而且因为对于您的示例,我们需要从Object -> Integer -> int开始(通过拆箱),所以不允许从ObjectInteger的第二步。


现在,如果您确实编写了这样的代码

Integer i = new Integer(5);
Object p = i;
int s = (Integer) p;

这会起作用。事实上,运行时的JVM(通过HotSpot)可能会准确地注意到你在做什么,并将上面的代码转换为:

int s = 5;

因为JVM可能足够聪明,可以准确地实现你作为人类所意识到的。

因此,虽然你必须编写语义正确的Java源代码(当等边的右侧是Object时,不做int i = someObj),编译器可能足够聪明,可以在你运行程序时为你内联所有源代码。

Upcasting

在案例object中转换为超类型,而downcasting在案例int中转换为子类型。始终允许向上转换,但向下转换涉及类型检查。

Object p=i;

在这里,您正在执行始终允许Upcasting因为int is an Object是有意义的。

int s = p; 

这里pobject,您正在尝试将其分配给子类型int,编译器如何知道p-objectint而不是字符串或双精度等。因此,要解决此问题,您必须像这样显式地进行向下转换:

int s = (int) p; 

注意:错误的向下转换可能会引发ClassCastException

最新更新