A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张宁 中级黑马   /  2013-3-11 00:17  /  6401 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Fu
{
    static String age()
    {
       return " I am a old man";
    }

  String name()
    {
       return "LaoZi";
     }
  }

class Zi extends Fu
{
     static String age()
    {
      return "I am a young man";
  }

  String name()
     {
     return "ErZi";
    }
}

class Test
{
    public static void main(String[] args)
   {
       Fu s = new Zi();
        System.out.println(s.age() + ", " + s.name());
     }
}\

为什么s的那么调用的是子类,而s的age却调用的是父类?

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

11 个回复

正序浏览
我的理解是:父类和子类有相同名字的静态方法,静态方法在内存中是同一个地址,而子类在继承父类的时候静态方法的名字没变,所以还是父类的那个方法的地址,子类在初始化的时候首先是调用父类的构造函数,故而内存中age就是父类的方法,而在Test中,对象初始化的类是子类,所以调用的name方法是子类的

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
因为子类其实是一种特殊的父类,因为Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换,或者被称为向上转型,向上转型是由系统自动完成的。
Java引用变量有两个类型,一个是编译时的类型,一个是运行时的类型。
编译时的类型是由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
如果编译时类型和运行时类型不一致,就会出现所谓的多态。
通过引用变量来访问其包含的实列属性和类成员时,
系统总是试图访问它编译时类所定义的属性和类成员,而不是它运行时类所定义的属性和类成员。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
  1. /*
  2. *在多态中,如果父类的引用指向了子类的对象,Fu3 f = new Zi3();
  3. * 多态中成员变量的特点:无论是否重名,静态, 无论编译还是运行,
  4. * 都参阅左边。即引用型变量所属的类的成员变量。注意:必须保证子
  5. * 类的调用的成员是父类有的。如果声明了多态,又调用子类特有的成员会导致编译失败。
  6. *
  7. * 多态中成员方法的特点:
  8. * 静态方法执行父类,非静态方法执行子类的。
  9. * static方法是“类”方法,方法调用信息是在编译的时候就已经决定了的。
  10. * Fu3 s = new Zi3();s的类类型是Fu3,编译的时候就定义了的。s.method();
  11. * 这一句在编译的时候就决定了用Fu3的method方法。
  12. **/
  13. public class DuoTaiDemo1
  14. {
  15.     public static void main(String[] args)
  16.     {
  17.         Fu3 s = new Zi3();
  18.         s.study();//调用的子类的方法
  19.         s.sleep();//调用的是父类的方法
  20.         System.out.println(s.age);//显示的是父类age
  21.         System.out.println(s.num);//显示的是父类num
  22.     }
  23. }
  24. class Fu3
  25. {
  26.     int age =1;
  27.     static int num =2;
  28.     public  void study()
  29.     {
  30.             System.out.println("Fu:study");
  31.     }
  32.    
  33.     public static void sleep()
  34.     {
  35.             System.out.println("Fu:sleep");
  36.     }         
  37. }
  38. class Zi3 extends Fu3
  39. {
  40.     int age = 3;
  41.     static int num =4;
  42.     public void study()
  43.     {
  44.         System.out.println("Zi:study");
  45.     }
  46.    
  47.     public static void sleep()
  48.     {
  49.         System.out.println("Zi:sleep");
  50.     }   
  51. }
复制代码
以上代码及思路也是在看到论坛上的问题及回答后整理出来的,希望对你有所帮助

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
在多态中  当父类引用调用 同名静态函数   和  变量(包括非静态)   一律调用父类的
回复 使用道具 举报
陈宇鹏 来自手机 中级黑马 2013-3-11 01:27:11
8#
因为,当静态方法进入内存时就已经被绑定了,绑定在方法的所属类上,所以在调用name时,其实调用的是父类的name,而非静态的则是动态绑定的,也就是相当于是this.age(),这里this被换成了s,s,又是指向子类对象,所以就直接去找子类对象中的方法了

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
李阳 中级黑马 2013-3-11 01:25:59
7#
class Fu
{
    static String age() //静态方法
    {
       return " I am a old man";
    }

  String name() //非静态方法
    {
       return "LaoZi";
     }
  }

class Zi extends Fu
{
     static String age() //静态方法
    {
      return "I am a young man";
  }

  String name() //非静态方法
     {
     return "ErZi";
    }
}

class Test
{
    public static void main(String[] args)
   {
       Fu s = new Zi(); //多态
        System.out.println(s.age() + ", " + s.name());
     }
}
Fu s = new Zi();父类引用指向子类对象。
因为name()方法是静态的,所以运行时调用的是父类的方法,
而age()方法是非静态的运行时调用的是对象的覆盖后方法,不是父类的方法。下面附上多态的规则:
多态中非静态成员函数的特点:父类引用子类对象 Fu f = new zi();
      在编译时期(只检查语法问题),参阅引用型变量所属类中是否有调用的方法。如果有,编译通过。没有,则报错。
      在运行时期,执行的是对象所属类中的方法。
      简单的说,非静态成员函数在多态调用时,编译看左边,运行看右边。
   多态中静态函数的特点:
       无论编译还是运行,都参阅左边。
多态中成员变量的特点:
     无论编译还是运行,都参阅左边。即引用型变量所属的类的成员

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
    这是子类继承父类的程序。当子类继承父类,沿袭了父类的功能到子类中,子类虽具备该功能,但是功能的内容却和父类不一致,这是,没有必要定义新功能,而是使用覆盖技术,保留父类的功能定义,并重写功能内容。子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。静态只能覆盖静态。Fu s = new Zi(); 由于是父类创建子类对象,成员函数在多态中调用时,编译看左边,运行看右边。所以结果为 I am a old man        Erzi

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
static  的属性和方法都是不能覆盖的,因为static修饰的部分都是与对象无关的,只与类有关
静态方法是和对象绑定的,也就是说子类覆盖了父类的静态方法,但是父类的静态方法还是和父类绑定的,只不过隐藏起来了.
Fu s = new Zi();//这句话是父类对象指向子类实例,也就是你new了一个父类对象,
age()是静态方法,所以调用的就是父类的

也不知道说的对不对.
回复 使用道具 举报
只要出现了静态,看声明的变量是类是什么,那么就是用这个类的 静态函数不复写,动态的就父的函数复写子类的内容

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
如果你是Zi Z=new Zi();那么就是输出你想要的结果
回复 使用道具 举报
你可以去看看毕老师第8天第5个视频:多态中成员的特点
在多态中成员函数的特点:
在编译发时期:参阅引用型变量所属的类中时否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行期间:参阅对象所属的类中是否有调用的方法
简单总结就是:成员函数在多态中调用时,编译看左边,运行看右边。
在多态中,静态成员函数的特点:
无论编译和运行,都看左边。
这里面涉及到动态绑定和静态绑定的知识。
class Fu
{
     static String age() //静态成员函数
     {
        return " I am a old man";
     }
   String name()
     {
        return "LaoZi";
      }
   }
class Zi extends Fu
{
      static String age()
     {
       return "I am a young man";
   }
   String name() //成员函数
      {
      return "ErZi";
     }
}
class Test
{
     public static void main(String[] args)
    {
        Fu s = new Zi();
         System.out.println(s.age() + ", " + s.name());
      }
}

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 鼓励鼓励

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马