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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张豪杰 中级黑马   /  2013-3-6 00:18  /  5159 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张豪杰 于 2013-3-6 13:19 编辑

子类继承父类,而且有相同的静态方法。
class Fu{
static void method(){
  System.out.println("fu method");
}

}
class Zi extends Fu{
static void method(){
  System.out.println("zi method");
}
}
class Practice {
public static void main(String[] args) {
  Fu f = new Zi();
  f.method();
}
}
这时候,子类方法无法覆盖。 “准确的讲此时只是子类对父类静态方法的隐藏(hide),子类的静态方法完全体现不出多态,就像子类字段隐藏父类的字段一样,在利用引用访问对象的字段或静态方法时,是引用类型(type)决定了事实上访问的是哪个字段,而非当前引用实际代表的是哪个类。因此,子类静态方法不能覆盖父类静态方法。”

想问大家的是,这里的引用类型决定访问的字段,为什么?

评分

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

查看全部评分

5 个回复

倒序浏览
Fu f = new Zi();
这里创建了个子类对象,并把地址给了f
首先这里创建对象对静态成员没有半毛线关系,因为静态成员都在类加载的时候首先放在静态区了,创不创建对象一个样。
Fu f 这里告诉虚拟机f 的类型是 Fu
根据一般静态成员调用方法  类名.静态成员,  所以就调用了父类的静态方法了。也就是说静态成员只认类型

评分

参与人数 1黑马币 +9 收起 理由
黄玉昆 + 9 赞一个!

查看全部评分

回复 使用道具 举报
因为子类其实是一种特殊的父类,因为Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换,或者被称为向上转型,向上转型是由系统自动完成的。
Java引用变量有两个类型,一个是编译时的类型,一个是运行时的类型。编译时的类型是由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现所谓的多态。
  1. public class People {

  2.         public String name="people";
  3.         public String getName() {
  4.                 return name;
  5.         }
  6.         public void setName(String name) {
  7.                 this.name = name;
  8.         }
  9. }
  10. public class BlackPeople extends People{
  11.         private String name="blackPeople";
  12.         public String getName() {
  13.                 return  name;
  14.         }
  15.         public void setName(String name) {
  16.                 this.name = name;
  17.         }
  18.         public static void main(String[] args) {
  19.                 People people=new BlackPeople();//编译时的类型是People,运行时的类型是BlackPeople;
  20.                 System.out.println(people.name);
  21.         }
  22. }
复制代码
通过引用变量来访问其包含的实列属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时类所定义的属性。

评分

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

查看全部评分

回复 使用道具 举报
调用父类的方法是因为多态。本题满足下面的第二条规则。
1.多态中非静态成员函数的特点:父类引用子类对象 Fu f = new zi();
      在编译时期(只检查语法问题),参阅引用型变量所属类中是否有调用的方法。如果有,编译通过。没有,则报错。
      在运行时期,执行的是对象所属类中的方法。
      简单的说,非静态成员函数在多态调用时,编译看左边,运行看右边。
  2. 多态中静态函数的特点:
       无论编译还是运行,都参阅左边。
3.多态中成员变量的特点:
     无论编译还是运行,都参阅左边。即引用型变量所属的类的成员变量。
class Fu{
static void method(){
  System.out.println("fu method");
}

}
class Zi extends Fu{
static void method(){
  System.out.println("zi method");
}
}
class Practice {
public static void main(String[] args) {
  Fu f = new Zi();//多态,父类引用指向子类对象。
  f.method();//由于多态的特性,实际调用的是父类的方法。
}
}

评分

参与人数 1黑马币 +9 收起 理由
黄玉昆 + 9 赞一个!

查看全部评分

回复 使用道具 举报
袁见 发表于 2013-3-6 01:01
因为子类其实是一种特殊的父类,因为Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换, ...

这个解释不错
回复 使用道具 举报
我想应该是这样的。。。。
当new zi()的时候类加载器会把子类和fu类都加载进内存
原因是,zi的构造函数当中,默认调用fu的构造函数,类中内容被使用,就要加载进内存
但是类中的静态成员,在类加载的时候,会存放到静态区中,这样静态区就有了fu类的method方法,和zi类的method
变量f当中存放的是zi类对象的地址值,我想当用f去调用method方法时,是会先根据地址值,到对内存中找到对象
并在对象内部去找有没有method方法,但是由于是静态成员,所以不是存在于堆内存,而是存在于静态区
竟然在对内存中找不到,我想虚拟机会根据引用的类型,到静态区中找对应的类中有没有该方法,找到后执行。

评分

参与人数 1黑马币 +9 收起 理由
黄玉昆 + 9 赞一个!

查看全部评分

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