下面这个程序中,输出的结果是:my name is wangwu and my age is 10
john
21我的想法是如果要是子类继承了父类的shout()方法,那么输出的应该是子类的name和age的值啊,怎么会是这样的输出结果???class Person
{
String name = "wangwu";
int age = 10;
public Person()
{
}
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
void shout()
{
System.out.println("my name is " + name +" and my age is " + age);
}
}
public class Student extends Person
{
String major;
String name = "lisi";
int age = 12;
public Student()
{
super();
}

public Student(String name,int age)
{
//super(name,age);
this.name = name;
this.age = age;
}

public static void main(String args [])
{

Student s1 = new Student("john",21);
s1.shout(); System.out.println(s1.name);
System.out.println(s1.age);
}

}
如果将下面程序段:
//super(name,age);
this.name = name;
this.age = age;
改为:
super(name,age);
//this.name = name;
//this.age = age;
程序的输出结果是:
my name is lisi and my age is 21
lisi
12给我的感觉好像是shout()方法中始终使用的是父类的成员变量name和age,而子类已经继承了父类,为什么在shout()方法中使用的不是父类的成员变量呢?请明示!!在内存中的状态又是什么样的呢?

解决方案 »

  1.   

    第一种情况:Student s1 = new Student("john",21);将参数john,21传给构造方法public Student(String name,int age)
    {
    //super(name,age);
    this.name = name;
    this.age = age;
    }在此构造方法中将参数符值给了name and age 故打印的是john,21,因为student 继承person 并没有重写shot()方法,故s1.shout();还是引用父类的方法故会输出my name is wangwu and my age is 10
    第二种情况:Student s1 = new Student("john",21);将参数john,21传给构造方法public Student(String name,int age)
    {
    super(name,age);
    //this.name = name;
    //this.age = age;
    }此构造方法super父类的方法,即public Person(String name, int age)
    {
    this.name = name;
    this.age = age;
    }这个时候就把子类里定义的name and age 值传了过去,所以输出的是lisi 12
    同样,由于此时子类super父类的方法,并将值john,21传给了父类的name and age ,故shout()显示结果为:my name is john and my age is 21
      

  2.   

    意思就是说父类的shout()方法虽然别子类继承了,但是使用的却是父类的成员方法,而不是子类的成员方法,是这样嘛?
      

  3.   

    总的来讲,还是关于动态绑定的问题只有非final或非static或非private的方法才是动态绑定的
    成员变量不是动态绑定的,所以shout()在编译时刻就已经决定了他使用的name和age.它们和shout()具有同样的名字空间.
    不管谁去调用,Person的shout()所使用的始终是Person类的name和age.把你的程序Person和Student各加了一个方法f(), 然后在shout()里面调用了f():
    class Person
    {
    String name = "wangwu";
    int age = 10;
    public Person()
    {
    }
    public Person(String name, int age)
    {
    this.name = name;
    this.age = age;
    }
    void shout()
    {
    f();
    System.out.println("my name is " + name +" and my age is " + age);
    }
    void f() {
    System.out.println("Person");
    }
    }
    public class Student extends Person
    {
    String major;
    String name = "lisi";
    int age = 12;
    public Student()
    {
    super();
    }

    public Student(String name,int age)
    {
    //super(name,age);
    this.name = name;
    this.age = age;
    }

    void f() {
    System.out.println("Student");
    }

    public static void main(String args [])
    {

    Student s1 = new Student("john",21);
    s1.shout(); System.out.println(s1.name);
    System.out.println(s1.age);
    }

    }这是结果:
    Student
    my name is wangwu and my age is 10
    john
    21
    可以看到,shout()方法中调用的是Student的f()方法.具体一点讲:
    用javap把Person.class打开,可以看到方法shout()中有这么几行:
       1:   invokevirtual   #5; //Method f:()V
       20:  getfield        #3; //Field name:Ljava/lang/String;
       32:  getfield        #4; //Field age:I
    其操作数所指的常量池为:
       const #3 = Field        #16.#33;        //  Person.name:Ljava/lang/String;
       const #4 = Field        #16.#34;        //  Person.age:I
       const #5 = Method       #16.#35;        //  Person.f:()V
    invokevirtual这个指令就是动态绑定的体现,虽然同样也是指向的f()也是Person类的,但是运行时虚拟机会根据实际类型决定f()的调用.
      

  4.   

    老大,很简单的问题弄这么多,你没有重载超类里的void shout()方法
    超类里打印的是超类的实例变量,你把超类里的这个方法重载一下!