代码附上,运行结果大家试一试就知道了,我很想知道为什么会是这个答案,十分费解!求原理
class SuperClass {
int var = 1;

public void print() {
System.out.println(var);
}
}class SubClass extends SuperClass {
int var = 2;

public void print() {
System.out.println(var);
}
}public class SSP {
public static void main(String[] args) {
SuperClass sp = new SubClass();
SubClass sb = (SubClass) sp;

System.out.println(sp.var);
sp.print();

System.out.println(sb.var);
sb.print();
}
}

解决方案 »

  1.   


    class SuperClass {
        int var = 1;    public void print() {
    System.out.println(var);
        }
    }class SubClass extends SuperClass {
        int var = 2;    public void print() {
    System.out.println(var);
        }
    }
    public class SSP {
        public static void main(String[] args) {
    SuperClass sp = new SubClass();//向上转型为sp ,只能看到父类的方法
    SubClass sb = (SubClass) sp;//向下转型为sb,可以看到自己独有的方法和重写后的方法 System.out.println(sp.var);//sp 只能看到父类的域
    sp.print();//sb 可以看到自己独有的域和覆盖后的域,可以看到自己独有的方法和重写后的方法 System.out.println(sb.var);//sb 可以看到自己独有的域和覆盖后的域,可以看到自己独有的方法和重写后的方法 sb.print();//sb 可以看到自己独有的域和覆盖后的域,可以看到自己独有的方法和重写后的方法    }
    }
      

  2.   

    父类是A,子类是B。
    回答你System.out.println(sp.var);这个问题吧。A a = new B();这一句的过程是这样的,
    1)创建一个类A的引用a
    2)创建一个类B的实例
    3)把类B的引用赋值给a因为A是B的父类,所以,赋值成功。
    过程:当消息发送到子类并要求以确定的参数调用其中一个方法时:消息的处理如下沿着类链自下而上逐级查找,直到找到符合消息所要求的方法为止。子类检查是否有同名且参数完全对应(参数的个数、类型、排列顺序均要相同)的方法,若有,就调用它,若没有,它的父类就响应这个消息的处理,查找同名及同参数个数、类型、顺序的方法,若有,就调用这个方法。如果查找到最上层仍未找到就会产生"编译出错"。子类中若有与其祖先类同名的并具有相同参数表的方法时,                             则具有屏蔽或隐藏其祖先类同名方法的功能。利用多态允许将一个对象声明为某个父类,而以扩展类实例化它(因为每一个子类都属于其超类的范围,从继承链的层次结构看,属于拓宽转换)。多态机制可以方便对象的管理。JVM可以根据实例的类型动态地调用实现相应的方法。
      

  3.   

    奇怪了 这里打印sp.print为什么调用的是sb的?不是应该只显示sp原有的吗?难道就因为那句强转超类的方法被完全覆盖了?已经无法调用了?
      

  4.   


    既然你提到了“父类引用指向子类对象,具体的实现过程由子类决定”,那为什么第一句调用的不是子类的var而是父类的var?print方法调用的不就是子类的方法了呀
      

  5.   

    LZ要理解继承和多态以及动态绑定。java中出来static方法和final(private方法属于final方法)之外,其他所有方法都是的动态绑定的。这些都是自己发生的,不用我们程序员去控制。 
    SuperClass sp = new SubClass();
    sp.print();
    知道print不是final和static的,那sp调用的时候就是动态绑定,动态绑定使得pringt方法运行时实际上是运行子类的print方法。所以sp.print()得到的结果是2就不好奇了。也许你理解了动态机制后,可能会认为所有事物都是可以多态地发生。但是,只有方法的调用可以是多态的。域也就是属性还有静态方法和final的方法都不是动态地发生。所以 System.out.println(sp.var);得到的就是1了。
    System.out.println(sb.var);//jvm会搜索sb的应用发现子类也就是自己的应用中就有这个属性就直接调用自己的val了。如果没有会找父类有没有val,有就调用父类的。会一层一层往上找,如果没找到则会报错。
    LZ可以试着把print方法改成static和final或者private的试试,就会得到不同结果了
      

  6.   

    还是说多态的作用是
    如果SuperClass sp = new SubClass();
    调用的如果是超类的域则直接用超类的;如果调用被子类覆盖的超类方法就用子类;如果调用超类的自有方法则照旧
    这句话对吗?
      

  7.   

    原来如此 static final private的方法是没有办法被子类覆盖的 所以调用的时候就没有动态绑定和多态了
    而不是以上三种的如果用到多态会根据子类是否覆盖动态绑定到子类的方法上
    以上仅针对方法 域除外
    总结完毕 结贴 今天又深入学习了一点多态 动态静态绑定 对继承的认识更深入了
      

  8.   

    SuperClass sp = new SubClass();//sp是子类上转型对象
    System.out.println(sp.var);//上转型对象sp访问的var是在父类中定义的var成员变量,故输出值为1sp.print();//上转型对象sp调用print()方法,由于该方法被子类重写,故上转型对象调用的print()方法是被子类重写的print方法,又由于在子类中定义了和父类同名的var成员,所以在子类中定义的var隐藏了在父类中定义的var,所以在子类重写的print方法中输出的是子类中定义的var变量的值,所以输出为2
    SubClass sb = (SubClass) sp;//sb是下转型对象,该下转型对象又具有了SubClass子类对象所具有的性质
    System.out.println(sb.var);//所以通过下转型对象sb访问var变量,同子类对象访问var变量作用一致,访问的是在子类中定义var变量值,故第三个输出为2
    sb.print();//其实可以将下转型对象看成是子类创建的对象,所以通过下转型对象sb调用的print方法是被子类重写的print方法,而被子类重写的print方法中输出的是在子类中定义的var的值,故第四个输出为2