覆盖是怎么样在运行时动态确定的,跟虚方法又有什么关系?

解决方案 »

  1.   

    虚方法?  Is it called abstract method?
      

  2.   

    虚方法是C++里的概念吧,不过C++用virtual指定方法为虚方法,用以支持多态,相关的是Virtual Table技术实现
    java默认所有的方法都是virtual的(final,private,static应该去掉了),内部如何支持的没仔细分析过,应该也是类似虚表的机制吧.
      

  3.   

    abstract method 应该就是这个吧,我刚刚听来的,以为可以这么简称
      

  4.   

    楼主说的覆盖是指的overload还是override?
      

  5.   

    No, you cannot. It confused us...
      

  6.   

    不要用C++的思维方式来学java
    它们概念有相识的 地方 ,但还是有区别的 
      

  7.   

    奥秘应该在方法表了吧,因为这是运行时的行为,所以从编译结果也看不出什么来,所以要分析方法表了,不过初学java,还不太懂.
    例子: 
    public class Test {    public static void main(String[] args) {
            Base base = new Base();
            base.print();
            Base sub = new Sub();
            sub.print();
        }
    }class Base {    public void print() {
            System.out.println("Base::print");
        }
    }class Sub extends Base {    public void print() {
            System.out.println("Sub::print");
        }
    }编译后的Test.classCompiled from "Test.java"
    public class Test extends java.lang.Object{
    public Test();
      Code:
       0: aload_0
       1: invokespecial #1; //Method java/lang/Object."<init>":()V
       4: returnpublic static void main(java.lang.String[]);
      Code:
       0: new #2; //class Base
       3: dup
       4: invokespecial #3; //Method Base."<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4; //Method Base.print:()V
       12: new #5; //class Sub
       15: dup
       16: invokespecial #6; //Method Sub."<init>":()V
       19: astore_2
       20: aload_2
       21: invokevirtual #4; //Method Base.print:()V
       24: return}
    编译器只知道根据类型确定调用的是Method Base.print:()V
    具体在方法表里怎么去匹配的就自己研究一下吧.
      

  8.   

    嗯 ,sorry,谢谢指点
    不过那个虚函数表又是什么东西?为什么会跟我的问题有关
    谁能告诉我哪种类型的书上能找到这个概念?最好就直接告诉我书的名字
      

  9.   

    invokevirtual,为什么用virtual这个词?呵呵
    不过重写的方法和重载的方法都会用到这个指令.
      

  10.   

    普通的成员函数与一般的非成员函数对连接器来说没什么区别,他们总是放在代码段中固定的位置,连接时直接将此地址连入即可。只是成员函数多一个this参数而已,用以区别当前对象的实例,从而能够存取到特定实例中的成员变量。也就是说,非虚成员函数与普通函数一样,是在连接的时候就“早绑定”好了的。   
      而虚函数不同,含有虚函数的每个类的对象,都要维护一个虚函数表,其指针其实就是该类的第一个成员(当然,对程序员来说是不可见的),运行时,首先通过类的实例得到虚函数表,然后从表中查到相应的函数入口,实现所谓的运行时“迟绑定”。所以,即使是用一个基类的指针,但如果它实际指向的是一个派生类对象,那么运行时,得到的虚函数表将是此派生类的虚函数表,最终调用的也将是派生类的函数。   
      当然,虚函数为了实现这种灵活的“迟绑定”,也必须付出代价,那就是每个对象都必须维护一张虚函数表,当虚函数很多时,这个表是很巨大的。
      

  11.   

    可以参考一下Inside Java Virtual Machine
      

  12.   

    <<Inside   the   C++   object   model>>
      

  13.   

    仅仅是参考一下 <<Inside   the   C++   object   model>>
     呵呵
      

  14.   


    有点好奇,怎么才能像你这样看到编译后的东西,是用什么打开的.class文件?
      

  15.   

    谢谢很详细,不过冒昧地问一下,这个说法是针对java的吧?还是java也是一样的?
      

  16.   

    这个问题要从面向对象的多态性讲起,多态性是指子类可以override父类的方法(final方法除外)。有一种特殊的类是抽象类,它包含的抽象方法只能在子类当中定义。在c++里面把这种方法成为虚方法,但是这个词在java里面已经不用了。关于如何在运行是确定该运行那个子类里的相关方法,可以参考“迟滞编译”或称“迟滞联编”的相关知识。
      

  17.   

    javap -c 类名(不写.class)
    就可以看对应的虚拟机指令代码了.
    简单的问题看指令就明白了,复杂的还要看里面的方法表,类型信息等.