实例方法和变量的情况下javainheritance解析

根据java,实例方法解析基于参数的运行时类型。

但在解析实例变量时,它使用不同的方法,如下所示。

节目输出是……

Child Parent ParentNonStatic 

这里第一个输出基于参数的运行时类型,但第三个输出不是。

谁可以解释一下这个?

  public class Child extends Parent { public static String foo = "Child"; public String hoo = "ChildNonStatic"; private Child() { super(1); } @Override String please() { return "Child"; } public static void main(String[] args) { Parent p = new Parent(); Child c = new Child(); //Resolving method System.out.println(((Parent) c).please()); //Resolving Static Variable System.out.println(((Parent) c).foo); //Resolving Instance Variable System.out.println(((Parent) c).hoo); } } class Parent { public static String foo = "Parent"; public String hoo = "ParentNonStatic"; public Parent(int a) { } public Parent() { } String please() { return "Tree"; } } 

在Java中,你实际上并没有“强制转换”。 当你要求转换时,Java实际上并没有任何事情,除了检查对象是否可以转换为该类型,因此转换为什么会抛出“ClassCastException”。

编译器虽然理解强制转换,因此使用它们来validation方法调用是否合适。

对于静态字段,编译器实际上删除了任何实例变量,并根据返回类型通过类引用该字段。

 Parent p = new Parent(); Child c = new Child(); Parent pc = new Child(); System.out.println(c.foo); // will print Child System.out.println(p.foo); // will print Parent System.out.println(pc.foo); // will print Parent System.out.println(((Child)pc).foo) // will print Child 

字段似乎以相同的方式工作。

我想简而言之,java对方法进行动态绑定,对字段进行静态绑定。

当你向上转换一个对象时,你实际上并没有改变你所引用的项目的内容,只是你对待它的方式。 因此,当你向父母转发c并调用please()时,你在Parent上调用please(),但是动态类型仍然是一个子类,所以真正调用的是子文件中的重写版本,并打印“Child”。

当你向上转换c并引用foo时,你没有进行函数调用。 编译器可以在编译时确定您所指的内容。 在这种情况下,具有父类型的对象的字段foo。 字段和静态字段不会被覆盖。 相反,它们是隐藏的。 你实际上最终用这个upcast做的是帮助Java选择隐藏版本(来自Parent的版本)而不是来自child的版本。 同样,通过hoo,您可以获得父版本。

以下是JAva教程的一些信息: http : //java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html

字段不会以与方法相同的方式覆盖。 通过将c转换为Parent,您指示“.hoo”指的是Parent上的“hoo”字段,而不是Child上的“hoo”字段。 (换句话说,技术上更正确,字段访问不是多态的。)