1、
-------------
class person{
          void say(){System.out.println("I'm a person.");}
}
class student extends person{
          void say(){System.out.println("I'm a person,but even a student.");}
}
class testOverlay{
          public static void main(String args[])
            {
                        person p=new student();
                            p.say();
             }

为什么这个程序输出是I'm a person,but even a student?
2、
----------------
那么这个呢?
class person{
          void say(person p){System.out.println("I'm a person.");}
}
class student extends person{
          void say(student s){System.out.println("I'm a person,but even a student.");}
}
class testOverlay{
          public static void main(String args[])
            {
                        person p=new student();
                        student s=new student();
                            p.say(s);
             }

为什么输出又是I'm a person.

解决方案 »

  1.   

    你还不太清楚继承的问题啊.
    因为p是根据person的类型信息创建的,所以p.say()会执行p的方法(第二种完全符合这种约定).至于第一种情况,嘿嘿,是因为它override了.
      

  2.   

    void say(person p){System.out.println("I'm a person.");}
     她调用的是这个方法。
    p.say(s)-〉p.say((Person)s)
      

  3.   

    class person{
              void say(person p){System.out.println("I'm a person.");}
    }
    class student extends person{
              void say(student s){System.out.println("I'm a person,but even a student.");}
    }
    class testOverlay{
              public static void main(String args[])
                {
                            person p=new student();
                            student s=new student();
                            p.say(s);//
    /********************************************
     *s是student类型,同时也是person类型,所以p.say(s);能通过编译,
     *p.say(person p)方法功能是什么,是System.out.println("I'm a person.");
     ********************************************/
                 }
    } //类名应该大写,变量起始字母才应该小写
      

  4.   

    Thinking in Java有详细的解释,去看一下就都明白了。
      

  5.   

    rcom10002(KNIGHTRCOM) 讲得不错,这里涉及一个继承时候方法得执行顺序以及上溯下溯造型的问题还有就是函数OVERRIDE的情况。THINKING IN JAVA里面对这些问题阐述得非常清楚,强烈建议去好好看看THINKING IN JAVA会对JAVA得基本原理有非常大得帮助的。
      

  6.   

    这不就是一个多态的例子吗?java用的是后绑定,所以当你声明一个对象是person时候,它直到执行时候才会绑定到他的某个具体的继承对象。在这个例子中不就是student的实例吗?
      

  7.   

    我一开始对第二个例子有些不懂,后来问过一个人后,知道了。原来,2中的两个Say方法的签名不同。因为参数类型不一样,这样。什么问题都清楚啦。哈哈。怪我自己没看清。
      

  8.   

    我承认我笨,看了半天还是糊涂.
    第二个例子,如果将:p.say(s) 改为:p.say((student)s) 输出还是: i'm a person
    根据动态绑定,p不是student类型吗?为什么还是调用父类的方法?
      

  9.   

    person p=new student();p申明成父类,只有父类的方法对他来说是可见的。所以就是调用父类的方法,虽然student继承了person类,但是方法void say(student s){...}只能算是对person类中void say(person p){...}的重载,并不是重写,如果把student中的方法改为void say(person s){...}的话就是所谓的重写,即多态
      

  10.   

    谢谢各位精彩的回复,谢谢!
    但还是不能完全理解,觉得有点牵强了。
    1、
    ---------------
    我想问下欧阳,你说“person p=new student();p申明成父类,只有父类的方法对他来说是可见的。”,既然这样,那第一个程序就应该输出I'm a person.
    2、
    --------------
    gccr既然你明白了我的问题,那可不可以把你的想法贴出来,让大家看看呢?
    3、
    -------------
    很多人都叫我去看Think in java,我也知道看它会得到答案,但现在没有那时间看书啊。所以上来问各位高手了。俗话说得好,听君一言胜读万年书啊,请各位不啬赐教。小弟在此谢过!!!!!!!!
      

  11.   

    呵呵,研究了一个中午,大概搞清楚怎么回事了。
    1、第一个例子:父类、子类的say()方法完全一样,属于正宗的多态性问题,这个就不解释了。
    2、第二个例子:由于student 的say(student s) 与父类的say(person s) 自变量参数不同,属于方法重载,不是覆盖,不能用多态性的动态绑定来理解。正如欧阳所说的,父类看不到子类的say(student p) 方法,因此输出"I'm a person".
      

  12.   

    第二个例子是一种函数重载,因为say()传入的两个参数根本不同,所以Person类的say()和Student类的say()根本就是两个函数。
    在声明时,p被声明成Person类,而被实例化成Student类,这时如果Student类中的有覆盖父类中的Say()方法则应该调用被覆盖的方法。但是在这个例子中没有被覆盖的方法,所以调用的还是父类的方法即say(person p)方法。而在传入参数时传的是person的继承类的对象,这也是允许的。反之如果方法中声明传入的是继承类的参数,则不允许传入父类的对象。