Java新手看多态时遇到这个问题,谁能给解释下

package test;

public class test{
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println(a1.show(b));

System.out.println(a1.show(c));

System.out.println(a1.show(d));

System.out.println(a2.show(b));

System.out.println(a2.show(c));

System.out.println(a2.show(d));

System.out.println(b.show(b));

System.out.println(b.show(c));

System.out.println(b.show(d));

}
}

class A {

public String show(D obj){

return ("A and D");

}

public String show(A obj){

return ("A and A");

}
}

class B extends A{

public String show(B obj){

return ("B and B");

}

public String show(A obj){

return ("B and A");

}

}

class C extends B{}
class D extends B{}

System.out.println(a1.show(b));
a1是A类型A对象
所以看参数
打印A and A
System.out.println(a1.show(c));
a1是A类型A对象
所以看参数
打印A and A
System.out.println(a1.show(d));
a1是A类型A对象
所以看参数
打印A and D
System.out.println(a2.show(b));
a2是A类型B对象
所以a2.show(b)是调用A类的方法,但是B类重写了这个方法
所以调用的是B类的方法
public String show(A obj){
return ("B and A");
}
打印B and A

System.out.println(a2.show(c));
a2是A类型B对象
所以a2.show(b)是调用A类的方法,但是B类重写了这个方法
所以调用的是B类的方法
public String show(A obj){
return ("B and A");
}
打印B and A
System.out.println(a2.show(d));
a2是A类型B对象
所以a2.show(b)是调用A类的方法,
B类没有重写该方法
打印A and D
System.out.println(b.show(b));
b是B类型B对象
调用B方法看参数
参数遵循就近原则
打印B and B

System.out.println(b.show(c));
b是B类型B对象
调用B方法看参数
参数遵循就近原则
打印B and B

System.out.println(b.show(d));

b是B类型B对象
调用B方法看参数
D继承A
调用父类的方法
打印A and D

问题说一下,你遇到什么问题了?

A是B的父类比如A是动物,B是狗或猫,C、D和A、B无关,要用父类接收子类,子类接收父类要强转,且强转要可行。

A是B的父类比如A是动物,B是狗或猫,C、D和A、B无关,要用父类接收子类,子类接收父类要强转,且强转要可行。

你的问题呢?没看到啊。。。

包装测试;公共课考试{ public static void main(String [] args){ a1 =新一a();A2 =新b();B =新b();C =新c();D =新d();系统。了。println(A1。显示(B));

问题是 输出的结果是什么 原因。我猜会这样问

如果A是父类,B是子类,你可以用B来实例化B,因为B包含了A,所以你可以用B来实例化A,其他的都是类似这样的。

没明白你的问题_

 A a2 = new B();a2.show(b)方法调用过程如下,先看a2的定义的变量类型是A,则去A类中招show方法,参数是B,没有对应的参数是B的show方法,找参数是父类的show方法,于是就是show(A obj),然后看new B(),在从B类中找show(A obj)
原理:
 子类继承父类的情况,在JVM加载载入父类和子类后,会在方法区构建自己的方法表,也就是有一个父类方法表,一个子类方法表。
子类方法表的构建是父类的方法-子类的方法,假设父类有方法A,子类覆盖了方法A。
对于父类方法表类似 
Object的方法
父类方法A的方法//这里只是突出一下,并不是说覆盖的方法排在第一个,实际这个方法的位置是固定的。
父类的其他方法

子类方法表类似
Object的方法
父类方法A的方法 //对于子类来说,这个位置还是原来父类方法A的位置,但这方法的执行时子类方法A
子类的其他方法

所以Father f = new Son(),调用f.A() 因为虽然是Father,但实际是Son,也就在Son的方法表中查找方法。然后又是Father调用,查找父类方法A的位置,这个位置在Son中是指向Son的方法A。就执行了子类的方法。

关键理解方法表、方法表中的偏移量、以及子类多态后相同方法的偏移量是与父类保持不变的。

楼主你好!
应该上面都很好理解,除了A a2 = new B();
这个a2看他类型是A,其实他真正是一个B类型的对象。因为A是B的父类,所以B可以作为A类的对象来使用。
但是在a2.show(b)的时候,调用的是B类的方法,是他实际的最原始的对象的方法。而不会调用A类的方法。
子类调用父类的方法,必须使用super关键字来调用。
比如在B类定义一个不一样的方法。
public aShow(D obj)
{
return super.show(obj);
}