大家好,初学java不久,遇到一个问题。现在有两个类,子类继承了父类的一个方法,并且子类覆盖了父类的一个同名属性。代码如下:
//BaseClass.java
package Example;public class BaseClass {
String name = "BaseClass";
public String getName(){
return name;
}
public String getInfo(){
return name;
}
}//SubClass.java
package Example;public class SubClass extends BaseClass{
String name = "SubClass";
public String getName(){
return name;
}
}
//Test.java
package Example;public class Test { public static void main(String[] args) {
BaseClass b = new BaseClass();
SubClass s = new SubClass();

System.out.println(b.getName());
System.out.println(s.getName()); System.out.println(b.getInfo());
System.out.println(s.getInfo()); }}
运行结果却为:
BaseClass
SubClass
BaseClass
BaseClass
怎么也想不通,为啥子类为何不能打印出自己的name属性,请大家指教!谢谢

解决方案 »

  1.   

    这不是很正确吗?楼主你想要哪一步打印自己的name呀?
      

  2.   

    你是要问最后一个对输出对不
    方法在定义的时候和动态绑定 不是一会事
    你在父类定义的方法 子类没覆盖 
    public String getInfo()
    这个方法的name只认 父类的name
    想想也知道 父类 知道谁会继承他吗? 他不知道这个方法的name 只认识父类的不认识子类的 如果还
    不明白请继续提问
      

  3.   

    你调用的是父类的getInfo方法 子类没有这个方法 所以它打出的是父类的属性
      

  4.   

    看楼主的问题 明显是问最后一个输出 楼主应该是认为最后一个输出该是子类的name
      

  5.   

    你子类的变量名和父类的变量名同名,所以子类的变量会覆盖父类的变量,如果想在子类里访问父类的同名变量请在变量名前加super关键字
      

  6.   

    s.getInfo() = s.super.getInfo()
      

  7.   

    public String getInfo(){
            return name;
        }相当于:
    public String getInfo(){
            return this.name;
        }
    this.name就指的是BaseClass.name
      

  8.   

    QQ137890732楼主你好:   这是个多态问题,对象是动态绑定的。它拥有了继承,并且重写了父类的方法。那么当运行期间就动态的生成对象。指向了对象重写的方法,如果对象没有重写,就指向父类的方法。   不知道这样说你能明白吗?或者我有说的不对的地方,请大家给我指出,或是发送到我的QQ邮箱中。
      

  9.   

    QQ137890732楼主你好:   这是个多态问题,对象是动态绑定的。它拥有了继承,并且重写了父类的方法。那么当运行期间就动态的生成对象。指向了对象重写的方法,如果对象没有重写,就指向父类的方法。   不知道这样说你能明白吗?或者我有说的不对的地方,请大家给我指出,或是发送到我的QQ邮箱中。
      

  10.   

    呵呵,这么多人这么晚了,还帮我解答问题啊,感动啊。
    我奇怪的地方确实是最后一句输出,按理说,SubClass已经继承了getInfo()函数了,它应该返回自己的name啊,为什么返回的却是父类BaseClass的name啊
      

  11.   

    那如果要打印子类的name,该怎么办?
      

  12.   


    那就在子类中重写getInfo()方法呗public String getInfo(){
            return name;
        }
      

  13.   

    我明白你的意思,按照你的想法 应该
    修改父类
    public String getInfo(String name) {
    this.name=name;
    return name;
    }
    修改主函数
    System.out.println(b.getInfo(b.name));
    System.out.println(s.getInfo(s.name));
    这样你就可以用父类的方法,准确的把你要的值返回去。
      

  14.   

    你原来的代码已经很好的说明了getinfo getName的返回值为什么不同
      

  15.   

    满意答案?
    说的够明白了都 你父类定义的方法其中的name 就指你父类的name
    千万别说什么覆盖了父类的同名属性 真覆盖了吗? 构造子类对象时 对象里照样有你父类的name 存在在你子类的对象内存中 请问楼主内存懂的多吗?覆盖 是指去掉以前的把新的盖上去 可是 变量根本不是这个效果 在子类对象里 照样有2个name 一个是子类里的 一个是父类里的 你调用父类的方法 那方法 抱歉 他只认识父亲的name 说白了 那个方法里的name 就和父亲类里的name绑在一起了 哪个子类调用这个方法都只能是父类的name 除非你在子类里重写这个方法!
      

  16.   

    public String getInfo(){
        return this.name;
    }
    说白了,父类的这个方法中默认name为this.name;当你实例化子类对象是,首先会实例化父类对象,那么这里this就是这个父类对象;因此getInfo方法返回的name是父类对象的name,除非你在子类中重写这个方法;
    在说白点,就是父类合子类的同名属性name在创建对象时根本是两码事,是两个地址完全不同的变量,而你方法中的this显然是指代父类对象,而不是子类对象
      

  17.   

    你说的这个和内存没关系,主要看JVM是如何实现的
      

  18.   

    天啊JVM 不就是管理内存吗 天啊
      

  19.   

    你的超类应该这么写:
    //BaseClass.java
    package Example;public class BaseClass {
        String name = "BaseClass";
        public String getName(){
            return name;
        }
        public String getInfo(){
            return getName();
        }
    }
      

  20.   

    我觉得,问题的根源是,子类的name属性并没有覆盖父类的name属性。
    我修改了一下代码,运行结果正好印证了我的想法:
    public class SubClass extends BaseClass{

    SubClass(){
    name = "SubClass";
    }

        public String getName(){
            return name;
        }
    }
    为SubClass追加了一个构造方法。然后运行Test。得到如下的结果:
    BaseClass
    SubClass
    BaseClass
    SubClass
    大家不信的可以自己试试。
      

  21.   


    这是java的规范,没有为什么。非要说为什么,我只能如下回答:C++有“许函数”的概念。就是说,在继承过程中,上下级中存在很多overRide的方法。在编译的时候,并不能确定在运行的时候执行哪一个方法。以搂住的例子来说,编译Test的时候,编译器不知道调用getName(),getInfo()是调用的父类的方法还是子类的方法。所有面向对象的程序最总还是顺序执行。怎么办呢?就引入一个“虚函数”的机制。在运行的时候来决定调用哪一个方法。这个机制就是调用继承树最底层方法。大家可能要说,可以让编译器扫描所有代码,让他在编译就定下调用哪一个方法。这样的做法有个问题。我们在使用别人写的jar包的时候,别人修改了代码,你就的重新编译一下你所有的东西,这样显然不是我们想要的,java设计者也认为这样不合理,所以就不是这样了。但是,有虚函数这个概念,却没有“虚属性”,“虚字段”这样的东西。对于字段的引用,直接查找当前类的字段。另外,只有非private的函数才是许函数,private生命的函数不是许函数。即:下面的测试代码,输出为Base
    package test;/**
     * @author aray
     * 
     */
    class Base {
    private void test() {
    System.out.println("Base");
    } public void exec() {
    test();
    }
    }class Sub extends Base {
    private void test() {
    System.out.println("Sub");
    }
    }public class Test {
    public static void main(String[] args) {
    Sub s = new Sub();
    s.exec();
    }
    }
      

  22.   


    这个提法是不对的,只有方法才有覆盖(overRide)的说法,属性(字段)是没有覆盖的说发的。无论是public还是private的属性,都不存在覆盖。如果大家调试一下程序,会发现,在继承树中如果有多个同名的字段,子类的实例里就有多个同名的属性,而不是一个名字的属性只有一个。
      

  23.   

    LZ最后一句:System.out.println(s.getInfo());
    子类中没有覆盖getInfo()这个方法,是不是应该调用父类的getInfo()方法?
    父类的getInfo()方法中的return name;你说这个name是子类的还是父类的?
    如果子类没有覆盖父类的属性,在子类中调用的name是父类的,但父类中的name还能是子类的?LZ有没有搞清楚继承关系是关键,不然再多的解释都白费。只有子类能继承父类的东西,父类本身里的方法所调用的属性必然是其自身的属性或是这个父类的父类,一个父类是怎么能知道将会由哪个子类来继承自己的?又怎么会调用到子类的属性的?
      

  24.   

    更正一下,36楼说的对,属性是没有覆盖的概念的,
    就是子类中没有与父亲同名的属性,调用的就是父类的,如果有同名的,在没有用super.来指明的情况下,默认调用的是自己。