java中的向上转换

java中的向上转换,java,casting,Java,Casting,在Java中,假设我有3个类,C从B扩展而来,B从A扩展而来 class X { interface A {} interface B extends A {} interface C extends B {} void f(A a) {} void test() { C c = new C() B b = (B) c; f(b); } } 如果我这样做,如上面的test()所示: C c = new C() B b

在Java中,假设我有3个类,C从B扩展而来,B从A扩展而来

class X {
   interface A {}
   interface B extends A {}
   interface C extends B {}
   void f(A a) {}

   void test() {
      C c = new C()
      B b = (B) c;

      f(b);
   }
}
如果我这样做,如上面的
test()
所示:

C c = new C()
B b = (B) c;

f(b);
f()
接受
b
作为类型
C
,因为
C
b
都是从
A
扩展而来的。我希望
f()
接收
b
类型
b
而不是类型
C

还有什么办法强迫这种向上转换吗?

f()
将始终接收键入为A的内容(尽管在封面下它实际上是A B或C,并且可以适当地向下转换)

您可以这样定义一个附加的f()

如果有必要

f(C c);
根据参数的类别,将调用正确的参数。i、 编译器根据参数的类型确定调用哪个函数。这与运行时发生的动态调度(或多态性)不同

请注意,您在问题中的角色是多余的。你可以写:

C c = new C()
B b = c;

f(b);
因为C是从B扩展而来的,所以C是B

我希望f接收b类型的b,而不是C类型的

A
C
是A
B
是A
A

f
内部,
f
只看到其参数
A
A
部分,如果
f
调用在
C
中被重写的公共
A
函数,则调用
C
重写

这就是虚拟函数的工作原理。这个想法是,所指的对象实际上是一个
C
,因此它应该表现出
C
行为。如果想要
B
行为,请传递
B
实例,而不是
C
实例

如果“C”和“B”应该具有相同的行为,请不要在
C
中验证该行为


你为什么要这样做?

你的问题毫无意义。你说的“f接受b为C型”是什么意思

f接受b作为类型A,因为方法签名是“A”。如果在b上调用方法,如果C重写它们,它们将在C上被调用。但这是Java中的标准行为(所有方法都类似于C++中的虚拟方法),无法更改


也许您可以描述您的实际问题,然后我们可能会提供帮助。

您似乎对编译时类型和运行时类型之间的差异感到困惑

您正在创建类型为c的对象(由引用c和b指向),它将保持为c,因为不可能更改对象的运行时类型和行为;通过强制转换,您只能更改其编译时类型,这会影响编译器如何处理它


你能提供一些关于你试图解决的具体问题的更多信息吗?很可能有一种方法可以通过改变设计来实现你的目标。

事实上,你可以将a的任何子类作为f(a)的参数传递是Java中OO固有的,您无法绕过此问题。如果C扩展了A,则始终可以在需要A的地方使用它。

您可以使用反射来检查参数是否属于A类:

public void f(A a) {
  if (a.getClass() == A.class) {
    // ok, go on
  }
  else {
    System.err.println("The parameter is not of class A!");
  }
}

不知道这是否是您想要的,但可能会有所帮助。

您的问题可以通过理解引用类型和实例类型之间的差异来解决。当您将C对象强制转换为B时,您只需更改引用类型-对象的实际实例仍然是C对象-如果您查看ob,这一点应该非常明显对象处于调试模式。更改引用类型仅影响编译器处理/感知代码的方式-不应影响运行时行为。对C对象的任何方法调用都将始终调用C的方法(无论该对象是否已强制转换为其他对象)。如果您对B中的方法进行了过度编码,并希望调用B版本的方法,则需要创建B实例。

事实上,您的代码引用了a,但这并不意味着指向的对象也是a。如果是a C,则仍然是C。源代码中的引用仅限制了源代码中可用的方法。强制转换仅为n这是必要的,因为有时需要在不同类型上使用方法,我们需要欺骗编译器,所以让我们开始在类型上使用方法。如果尝试无效,则在运行时强制转换自然会失败。

这正是我试图理解的。我希望参数显示B行为。我想我必须创建一个新的在将参数传递给f之前,请从C中调用B实例。谢谢。如果希望f对B进行操作,为什么不创建一个B?C从何而来?我希望f根据其类型调用参数的方法,因此如果参数是C,我希望调用C.deliverTo(),但如果参数是B,我希望调用B.deliverTo()。谢谢。是的,还有另一种方法可以完成我想要的任务,我可以从a C创建B的新实例,但我想了解为什么我不能用我第一次尝试的方法来完成:)谢谢。
In upcasting and downcasting the  object first upcast then downcastenter
class A
{
}
class B extends A
{
}
Class M
{
  psvm(String ar[])
{

   A a1= new B();
   B b2=(B)a1;
}
In upcasting and downcasting the  object first upcast then downcastenter
class A
{
}
class B extends A
{
}
Class M
{
  psvm(String ar[])
{

   A a1= new B();
   B b2=(B)a1;
}