package temp;class SubClass {
int a = 1;
public int getA(){
return a;
}
}class ChildClass extends SubClass {
int a = 2;
// public int getA(){
// return a;
// }
}public class Temp8 {
public static void main(String[] args) {
                //(1) s,c都是指向子类的引用,它们的根本区别在哪里?
SubClass s = new ChildClass();
ChildClass c = new ChildClass();
                //(2)既然s,c都是指向子类的引用, 为什么s.a打印的是父类中的a,而c.a打印的是子类的?
System.out.println(s.a);
System.out.println(c.a);
                //(3)SubClass中的getA()既然会被继承,那么ChildClass中注释掉的部分,注释与否为什么会对结果产生影响?(不注释返回的是ChildClass中的a,注释掉返回的是SubClass的a)
System.out.println(s.getA());
System.out.println(c.getA());
}
}请大家来看看(1)(2)(3)这三个问题,先谢过

解决方案 »

  1.   

    对于问题(1),我已经知道的是对于子类附加的接口(如子类中重新定义一个方法a()),通过子类类型引用可以调用(如c.a()),而父类类型引用不可以(如s.a()会报错)
      

  2.   

    (1) 一个是父类型的引用一个是子类型的引用,子类可以向上转型,父类不可以向下转。
    (2)s 本身是一个父类行的引用当然打印的是父类的引用了,子类继承了父类的引用但是覆盖了父类的属性,在继承的时候,方法和属性都是可以继承的。所以c.a打印的是子类的值
    (3)方法覆盖了之后获取的a的值是子类的,如果注释掉后,继承了父类方法那么a的值是父类的。你要看的是这个方法本身是属于子类还是父类。
      

  3.   

    (1) s,c都是指向子类的引用,它们的根本区别在哪里?
    在编译期s和c都是指向父类的引用,在运行的时候s会调用父类里的属性和方法,而c会调用子类的属性和方法,因为java里的方法是动态绑定的,这就多态(2)既然s,c都是指向子类的引用, 为什么s.a打印的是父类中的a,而c.a打印的是子类的?
    因为运行时s是一个指向父类对象的父类引用,c是一个指向子类对象的父类引用,而属性和方法都是动态绑定的,所以s打印出的是父类里的属性c打印出的是子类里的属性(3)SubClass中的getA()既然会被继承,那么ChildClass中注释掉的部分,注释与否为什么会对结果产生影响
    不注释掉不会对结果产生任何影响,但是运行时其实运行的是两段代码,原因还是动态绑定,调用s.getA()访问的是父类里的方法,调用c.getA()访问的是子类里的方法。
    不会产生影响是因为你两个方法写的有一样,如果你把子类里的方法改成return a+1;那s.getA()就返回2,c.getA()就返回3.
      

  4.   

    (1) s,c都是指向子类的引用,它们的根本区别在哪里?
    子类继承基类所有的属性和方法。根本区别应该通过(2)、(3)来体现。(2)既然s,c都是指向子类的引用,为什么s.a打印的是父类中的a,而c.a打印的是子类的?
    SubClass s = new ChildClass();父类引用指向子类对象,会调用父类的属性。
    ChildClass c = new ChildClass();子类引用指向本身对象,没啥说的,自己的东西优先用。(3)SubClass中的getA()既然会被继承,那么ChildClass中注释掉的部分,注释与否为什么会对结果产生影响
    子类中重写父类方法会覆盖掉方法,等同于父类方法不起作用。
    这些都是因为内存机制所决定的,体现是语言的表现形式就是多态和动态绑定。在面向对象的代码中,动态绑定意味着决定哪个方法被调用或哪个属性被访问,你这样记住就好了。
      

  5.   

    1,  s,c 都是子类对象,只是 s 是用父类来声明, 子类来创建的对象
    c 是子类声明并且创建的对象2,用父类声明的子类对象, 只能用父类的属性和方法,子类的本身的属性和方法用的时候是看见不的,
    而用这个对象调用父类方法时,如果子类重写了父类方法,那么执行的是子类的方法体 ,但属性还是父类的不变
    这就是多态 (属性看声明,方法看对象)
    所以,s.a 是父类声明的属性,a=1; c.a 是子类声明的属性 a = 2s.getA() 是父类的方法,在子类中被重写了,因此执行子类的方法体 返回 2
    c.getA() 本身就是子类声明创建的对象的方法, 返回值也是2关于继承,如何楼主认可上述所说,那么请楼主 想明白 (属性看声明,方法看对象) 这句就可以了
    并且,java的接口 声明 的多态 都是这么个意思  
      

  6.   

    我也来说说我的理解:输出结果: 1  2  1 1 假如在ChildClass中加上getA()方法,输出结果:1 2 2 2 1、一个是父类型的引用一个是子类型的引用,子类可以向上转型,父类不可以向下转。2、SubClass s = new ChildClass();
       ChildClass c = new ChildClass();
       从这里可看出来,在JVM编译期的时候,只会认为S是 SubClass.class ,c 是 ChildClass.class ,也就是说s除了SubClass.class 意外的信息都不知道,而对于子类ChildClass.class 的成员都不知道,也就是说除了父类ChildClass.class 以外,s无法访问ChildClass.class的成员,s.a是绝对报错的假如子类中有对父类方法的重写,那么根据多态机制,通过s访问这个方法的时候实际访问的是子类中重写的方法。为什么这样可以?上面说了,s只能访问SubClass.class的信息(注意这里指的是编译期编译器只知道s是SubClass类型,不知道s具体指向什么对象,运行期才知道指向什么对象),而子类重写的方法,父类中也存在,即ChildClass.class重写的方法,SubClass.class里也有(如果ChildClass.class里有但是SubClass.class里没有的方法,s也不能直接调用),所以s可以访问,但是调用的时候(注意这里指的是运行期),s实际指向的是ChildClass对象,所以调用的是ChildClass对象的方法。3、ChildClass 并没有重写SubClass 中的getA()方法,所以调用的是SubClass中的方法,而a在SubClass中的值为 1 ,故,s.getA() -->1在此:     如果子类重写的方法中访问了专属于子类的成员变量,这时候通过父类引用s还可以调用那个被重写的方法吗?    要分清编译期和运行期,编译期是编译器检查语法和类型,运行期是解析器解析伪代码为机器指令而执行,编译期编译器会检查s的访问范围,也就是s的访问不超过SubClass.class的信息就不会出错,运行期解析器会解析方法的代码指令,因为s指向子类对象,所以会解析子类重写的方法代码指令,而子类对象的内存空间是包含子类的成员变量的空间的,所以也不存在子类成员变量没有分配内存的问题,所以可以调用。  
    再说   :  加上ChildClass中的getA()方法,也就是重写了父类的方法,而return a, 在ChildClass中a这个成员变量被重写了,所以 s.getA() -->2   c.getA() -->2参考帖子:http://topic.csdn.net/u/20120613/11/4bd36b8d-2ce1-4640-9969-a8bd24fe20e1.html以上是我结合自己的理解以及帖子的参考得到最满意的答案,请大家多多指点
      

  7.   

    不好意思,有一点地方特来补充说明下:2、SubClass s = new ChildClass();
      ChildClass c = new ChildClass();
      从这里可看出来,在JVM编译期的时候,只会认为S是 SubClass.class ,c 是 ChildClass.class ,也就是说s除了SubClass.class 意外的信息都不知道,而对于子类ChildClass.class 的成员都不知道,也就是说除了父类ChildClass.class 以外,s无法访问ChildClass.class的成员,s.a是绝对报错的(这里的a指的是ChildClass中的)-->特指编译期而在运行期的时候:s.a -->a指的则是父类的
    对了,其中 7 楼的回复也不错……