黑马程序员技术交流社区

标题: 在多态中,静态成员函数的特点是什么 [打印本页]

作者: 马晓平    时间: 2013-10-21 23:16
标题: 在多态中,静态成员函数的特点是什么
本帖最后由 马晓平 于 2013-10-27 11:26 编辑

在多态中,静态成员函数的特点是什么?
作者: 回天之力    时间: 2013-10-21 23:44
在多态中,静态成员函数的特点:无论编译和运行都参考左边。
作者: wenbaoxing    时间: 2013-10-22 10:07
fu f = new zi();
在多态中成员函数的特点:
在编译时期:参阅引用型(f)变量所属的类中是否有调用的方法。如果有,编译通过。
在运行时期:参阅对象所属的类中是否调用的方法。

在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。

毕老师提到了动态绑定和静态绑定



程序绑定的概念:
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定

静态绑定:
在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。
针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定

动态绑定:
后期绑定:在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必 须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确 的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

动态绑定的过程:
虚拟机提取对象的实际类型的方法表;
虚拟机搜索方法签名;
调用方法。

在java中,几 乎所有的方法都是后期绑定的,在运行时动态绑定方法属于子类还是基类。但是也有特殊,针对static方法和final方法由于不能被继承,因此在编译时 就可以确定他们的值,他们是属于前期绑定的。特别说明的一点是,private声明的方法和成员变量不能被子类继承,所有的private方法都被隐式的 指定为final的(由此我们也可以知道:将方法声明为final类型的一是为了防止方法被覆盖,二是为了有效的关闭java中的动态绑定)。java中 的后期绑定是有JVM来实现的,我们不用去显式的声明它。


作者: wenbaoxing    时间: 2013-10-22 10:14
在多态中,父类和子类有同名的静态方法,在调用时是这样写的Fu f=new zi();那是会运行父类的静态方法那还是会运行子类的静态方法,为什么???

我们假设Fu f=new zi();"="号作为"左边","="右边作为"右边",在多态中有以下特点:
(1)静态成员函数的特点:无论编译和运行,都参考左边(引用型变量所属的类),就是会运行父类的静态方法。
(2)非静态函数的特点:在编译时期,参阅左边(引用型变量所属的类)是否有调用的方法,如果有,编译通过,如果没有编译失败。
      在运行时期,调用的是子类的方法,
      简单总结一下:非静态成员函数在多态调用时,编译看左边,运行看右边
(3)对于成员变量的特点:无论编译和运行,都参考左边(引用型所属的类),即运行父类的成员变量。
例如:
class Fu{
     int num=3;
}
class Zi extends Fu{
     int num=8;
}
class Test{
   public static void main(String []args){
       Fu f=new Zi();
       System.out.println(f.num);
       Zi z=new Zi();
      System.out.println(z.num);
  }
}
运行结果为:3,8

首选,即便是同名的静态方法,但是在内存的方法区中,也是分别根据类名保存的。所以不会冲突,但是如果是非静态的方法,那么调用的就是子类的方法了,同样的方法因为子类对象中重写了父类中的方法,所以父类的引用指向子类的实例对象。就好比你这个父类是人,实例对象是子类的男人。当你调用父类引用的撒尿后,自然调用的就是男人的站着撒尿的方式,你这个对象是男人。。不是女人,和太监。。

在继承中有一点比叫特别:
那就是同名的静态方法是不能覆盖的,这一点你的验证代码就可以看到,
同样,静态的变量也是不能覆盖的,如:
class Fu{
static int num=3;
}
class Zi extends Fu{
static int num=4;

}
通过引用父类的对象建立子类的对象的话,你得到的结果结果num=3;
因为在内存中静态成员在类开始加载时就存在于类中一特殊的内存中,它没有实例对象,它会一直存在而不改变,知道程序运行结束!





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2