class A1
{
String s = "class A";
void show()
{
System.out.println(s);
}
}
class B extends A1
{
String s = "class B";
void show()
{
System.out.println(s);
}
}
public class TypeConvert
{
public static void main(String[] args)
{
B b1;
B b2 = new B();
A1 a1,a2;
a1 = (A1)b2;
a2 = b2;
System.out.println(a1.s);
a1.show();
System.out.println(a2.s);
a2.show();
b1 =(B) a1;
System.out.println(b1.s);
b1.show();
System.out.println(b2.s);
b2.show();
}
}
就是不明白他们的转换
为什么b2转换成a1后还能输出a1.show();还会输出classB呢?
求详解

解决方案 »

  1.   

    show()方法被重写,子类可自动转为父类。
    动态绑定
    引用类型
      

  2.   

     a1 = (A1)b2;
    a1.s的值为什么是classB而不是classA呢
      

  3.   

    就像楼上说的, a1 = (A1) b2 这句到底是怎么运行的?javap -p -c TypeConvertCompiled from "TypeConvert.java"
    public class TypeConvert extends java.lang.Object{
    public TypeConvert();
      Code:
       0: aload_0
       1: invokespecial #1; //Method java/lang/Object."<init>":()V
       4: returnpublic static void main(java.lang.String[]);
      Code:
       0: new #2; //class B
       3: dup
       4: invokespecial #3; //Method B."<init>":()V
       7: astore_2
       8: aload_2
       9: astore_3
       10: aload_2
       11: astore 4
       13: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       16: aload_3
       17: getfield #5; //Field A1.s:Ljava/lang/String;
       20: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       23: aload_3
       24: invokevirtual #7; //Method A1.show:()V
       27: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       30: aload 4
       32: getfield #5; //Field A1.s:Ljava/lang/String;
       35: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       38: aload 4
       40: invokevirtual #7; //Method A1.show:()V
       43: aload_3
       44: checkcast #2; //class B
       47: astore_1
       48: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       51: aload_1
       52: getfield #8; //Field B.s:Ljava/lang/String;
       55: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       58: aload_1
       59: invokevirtual #9; //Method B.show:()V
       62: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
       65: aload_2
       66: getfield #8; //Field B.s:Ljava/lang/String;
       69: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       72: aload_2
       73: invokevirtual #9; //Method B.show:()V
       76: return}从这段代码里看,强制转换似乎没有发生,应该是编译期就处理了。
      

  4.   

    这是jvm在寻找实例变量和实例方法时,采用的不同策略造成的。
    a1 = (A1)b2,这句话的意思是“父类引用指向子类对象”,其中子类对象的对象在堆中分配内存,堆中是子类的对象,这个对象有个指针指向方法区中装载的子类(B),然后在子类的静态常量池查找S,得到classB;
    而实例方法的时候是根据方法表来查找的,每个对象有自己的方法表,其中有自己的方法和集成自父类的方法,这个方法表是根据你声明的对象类型来关联的,由于是父类(A)的引用,所以会查找A的方法表,如果查找不到,继续向上查找其父类(这里应该是object)的方法。
      

  5.   

    a1 = (A1)b2;
    a1.s的值为什么是classB而不是classA呢?
    对于这个问题 我是这么理解的。java类属性是没有覆盖多态这些概念的。
    如果是A的引用它的属性值就是先到父类找。找到了用父类的没找到就到子类找。
    而方法就不一样。方法有覆盖多态这一概念
    如果A的引用指向B它会先到子类找是否有相应方法有就调用子类的没有就到父类中找。。
      

  6.   


    System.out.println(a1.s);
    输出的就是classA
    你看错了
      

  7.   

    呵呵,运行的结果和我想的一样,用父类的引用去调用子类的属性时,会先到父类里找,如果找到了就会直接返回,所以实际得到的是父类的属性值。而用父类的引用去调用子类的方法时却不同,它也会先到父类中找,不过不管有没有找到,它都会再到子类中去找,如果在子类中找到,就会调用子类的方法。不知道这样讲你听明的了没有,如果还想知道为什么会这样你可以去看一下这本书.<深入JAVA虚拟机>
      

  8.   

    去看看java虚拟机相关的书 说的很明白的