当向上转型对象时,哪些部分是指向父对象的,哪些部分是指向子对象的?

huangapple go评论74阅读模式
英文:

When upcasting an object, what parts refer to the parent and what parts refer to the child?

问题

在下面的示例中,我感到困惑的是为什么向上转型似乎引用了父类的某些部分以及实际类的某些部分。

public class B extends A{
   int fi = 15;
   public static void main(String[] args){
       B b = new B();
       b.fi = 20;
       System.out.println(b.fi);
       System.out.println(  (  (A) b  ).fi  );
       System.out.println(  (  (A) b  ).getNum());
   }
   public int getNum(){
       return fi;
   }
}
class A{
   final int fi = 5;
   public int getNum(){
       return fi * 2;
   }
}

打印的结果是:

20
5
20

我知道这段代码写得有些低效,但它类似于我得到的一个OCA练习问题。我想知道为什么 ((A)b).fi 引用了 A 类中的变量,但 ((A)b).getNum() 使用了 B 类中的变量和方法。如果向上转型是指父类,那么结果不应该是 20 5 10 吗?

英文:

In the example below, I am confused as to why upcasting seems to refer to some parts of the parent class and some parts of the actual class.

public class B extends A{
   int fi = 15;
   public static void main(String[] args){
       B b = new B();
       b.fi = 20;
       System.out.println(b.fi);
       System.out.println(  (  (A) b  ).fi  );
       System.out.println(  (  (A) b  ).getNum());
   }
   public int getNum(){
       return fi;
   }
}
class A{
   final int fi = 5;
   public int getNum(){
       return fi * 2;
}

The printed results are:

20
5
20

I know this code is written in some inefficient ways, but it's similar to an OCA practice question I've gotten. I would like to know why ((A)b).fi refers to the variable in A, but that ((A)b).getNum() uses the variable and method in B. If upcasting refers to the parent, shouldn't the results be 20 5 10 instead?

答案1

得分: 0

这里有两种力量在起作用:

一方面,Java编译器使用引用的类型来解析类成员的名称。因为((A)b)具有类型A

  • ((A)b).fi指的是A中的变量fi
  • ((A)b).getNum()指的是A中的方法getNum。你可以通过在A.getNum()声明中添加一个已检查异常,同时不在B.getNum()中添加异常来验证这一点。编译器将要求你捕获或声明((A)b).getNum()可能抛出的异常,而允许你调用b.getNum()而不做任何更改。

另一方面,Java具有方法的动态分派。动态分派意味着在运行时,JVM查看实际对象的类型。如果对象重写了你正在调用的方法,JVM将调用重写的方法。这意味着:

  • ((A)b).getNum()将在运行时调用B中定义的方法。
英文:

There are two forces at play here:

On one hand, the Java compiler uses the type of the reference to resolve names to class members. Because ((A)b) has type A:

  • ((A)b).fi refers to the variable fi in A.
  • ((A)b).getNum() refers to the method getNum in A. You can see this for a fact by for example adding a checked exception to A.getNum() declaration, while leaving the exception out of B.getNum(). The compiler will require you to catch or declare the exception ((A)b).getNum() may throw, while it lets you call b.getNum() without such changes.

On the other hand, Java has dynamic dispatch for methods. Dynamic dispatch means that at run time, the JVM looks what what is the type of the actual object. If the object overrides the method you are calling, the JVM calls the override instead. This means:

  • ((A)b).getNum() will call the method defined in B at run time.

答案2

得分: 0

这个方法是由动态类型(B)选择的,但属性是由静态类型(A)选择的。

也许以下链接之一可以帮助您:

英文:

The method is chosen by the dynamic type (B) but the attribute is chosen by the static type (A).

Maybe one of the links can help you:

huangapple
  • 本文由 发表于 2020年8月14日 00:43:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63399649.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定